【问题标题】:Next.js Protect Routes Which Use Static Site GenerationNext.js 保护使用静态站点生成的路由
【发布时间】:2021-03-29 15:14:56
【问题描述】:

在 Next.js 中,您可以选择 server side rendering (SSR)static site generation (SSG)。在整个 Next.js docscommunity 中,出于性能原因,建议使用 SSG 而不是 SSR。

我有一个 Next.js 构建,它在整个应用程序中使用 SSG,使用 getStaticProps() 等通过与外部 CMS (Prismic) 集成在构建时生成内容/页面。我更喜欢这个,因为如前所述,它可以提高性能,并且大多数代码库都可以使用相同的数据获取策略(在构建时)。

但是,其中一些页面需要保护 - 这意味着它们只能由经过身份验证的用户访问。我们正在使用 Auth0 生成 JWT 令牌,并让 React 上下文提供程序在 API 调用中验证令牌后保存用户的状态(登录或未登录)。

但是,我很震惊我似乎没有用这个令牌保护 SSG 页面的好方法。推荐的方式 here 让我觉得很奇怪,因为据我所知,这是一个客户端重定向,可以由客户端操纵(例如 - 客户端可以操纵它的本地状态/ context 或篡改从notloggedincondition) 返回的任何内容以显示静态内容或以其他方式短路重定向。

作为参考,这里是该代码的粘贴:

import {useEffect} from 'react'
import {useRouter} from 'next/router'
export async function getStaticProps() {
  return {
    props: {
      hello: 'Hello World'
    }
  }
}

export default (props) => {
  const router = useRouter()
  useEffect(() => {
    if(notloggedincondition) {
      router.push('/login')
    }
  }, [])

  return <h1>Rest of the page</h1>
}

注意&lt;h1&gt;Rest of the page&lt;/h1&gt; 仍然可以通过操作客户端来访问...所以我想在请求/响应级别保护 SSG 并执行服务器端重定向(如果需要)或类似的操作。

没有像this 这样的东西,有没有办法在不依赖客户端路由的情况下安全地保护 SSG 页面?我是否需要对内容进行 SSR,即使它与其他内容实际上没有什么不同,除了只有经过身份验证的用户才能看到它的要求?

也许我遗漏了一些明显的东西,但在我看来,即使是静态站点,也应该有一种方法来保护它而不依赖于客户端路由。也就是说,静态生成网站的概念似乎并不是每个页面都必须是公共的,所以我想知道在 Next.js 中是否有一种安全的方法。

【问题讨论】:

    标签: security next.js


    【解决方案1】:

    我能找到的最佳方法是通过SWR fetches,静态生成带有初始未受保护静态数据的页面骨架,然后在刷新返回内容时对其进行水合。

    这确实需要您将收集数据的逻辑移动到 API 或 CMS 后面(任何会清除您的权限视图的东西),并且将现有路由转换为使用 API 调用并非易事,因此 YMMV。

    重要提示:您的重定向仍需要在客户端,但您可以避免将任何受保护的内容显示给未经授权的用户,因为这些内容仍会受到控制在服务器级别。由于您最担心的似乎是用户积极尝试通过操纵代码来破坏内容,这似乎符合您的风险补救标准(他们仍然无法访问受保护的内容)。

    示例页面代码:

    import {useEffect} from 'react'
    import {useRouter} from 'next/router'
    import useSWR from 'swr'
    
    export async function getStaticProps() {
      return {
        props: {
          hello: 'Hello World'
        }
      }
    }
    
    export default (props) => {
      const router = useRouter()
    
      // Access the protected content via an API route, 
      // provide the initial unprotected static content via the initialData param
      const { data } = useSWR('/api/protected-content', fetcher, { initialData: props })
    
      useEffect(() => {
        if(notloggedincondition) {
          router.push('/login')
        }
      }, [])
    
      return <h1>{ data.hello }</h1>
    }
    

    然后,pages/api/protected-content 的示例 API 实现:

    export default async function ProtectedContent(req, res) {
      // Get a session object based on request cookies
      let session = await initUserSession(req, res);
    
      // If a session is available, return the protected content
      if (session.props.userSession) {
        return res.status(200).json({hello: 'This is protected content'});
      } else {
        return res.status(401).send("UNAUTHENTICATED");
      }
    }
    

    【讨论】:

    • 我目前正在工作中解决这个问题,并且我一直在使用这种方法。 api 验证用户可以访问的敏感数据的水合。
    【解决方案2】:

    在工作中遇到了同样的问题,选择了一个自定义的服务器,放在 Next.js 前面。

    我们使用的是 Express,但任何 Node 框架都可以正常工作。这让我们可以将身份验证问题转移到单独的服务器框架,然后将请求转发到 Next.js。

    https://nextjs.org/docs/advanced-features/custom-server

    【讨论】:

      猜你喜欢
      • 2020-02-04
      • 2021-01-20
      • 2022-08-16
      • 2015-01-01
      • 1970-01-01
      • 2021-04-19
      • 2022-08-15
      • 1970-01-01
      • 2020-07-22
      相关资源
      最近更新 更多