你如何处理 NextJS 应用程序中的公共和私有路由?

IT技术 reactjs next.js
2021-05-21 09:52:17

我正在开发一个应用程序,我们有公共和管理路由,在我们过去的 CRA 应用程序中,我们使用了自定义路由元素,但我们在 nextjs 中没有……我们有很多公共页面,我们有 20私人页面/路线。

在nextjs中处理受保护的认证路由和公共路由的最佳方法是什么?

非常感谢!最好的

4个回答

我个人一直为此使用 HOC(高阶组件)。

这是一个示例身份验证 HOC:

const withAuth = Component => {
  const Auth = (props) => {
    // Login data added to props via redux-store (or use react context for example)
    const { isLoggedIn } = props;

    // If user is not logged in, return login component
    if (!isLoggedIn) {
      return (
        <Login />
      );
    }

    // If user is logged in, return original component
    return (
      <Component {...props} />
    );
  };

  // Copy getInitial props so it will run as well
  if (Component.getInitialProps) {
    Auth.getInitialProps = Component.getInitialProps;
  }

  return Auth;
};

export default withAuth;

您可以将此 HOC 用于任何页面组件。下面是一个使用示例:

const MyPage = () => (
  <> My private page</>
);

export default withAuth(MyPage);

如果需要,您可以使用角色检查(如公共、普通用户和管理员)扩展 withAuth HOC。

我认为这取决于页面的类型。

对于静态生成的页面:

您可以像@AleXius 建议的那样使用 HOC 进行身份验证。

对于服务器端呈现的页面:

您可以在getServerSideProps.

export async function getServerSideProps(context) {
  const sendRedirectLocation = (location) => {
    res.writeHead(302, {
      Location: location,
    });
    res.end();
    return { props: {} }; // stop execution
  };

  // some auth logic here
  const isAuth = await authService('some_type_of_token')

  if (!isAuth) {
    sendRedirectLocation('/login')
  }

  return {
    props: {}, // will be passed to the page component as props
  }
}

对于带有自定义服务器的服务器端渲染页面:

根据您选择的服务器,您可以选择不同的解决方案。对于 Express,您可能可以使用 auth 中间件。如果您愿意,也可以在getServerSideProps.

除了使用 HOC 的解决方案之外,您还可以使用 next 中的 ssr 方法,例如 getServerSideProps,在这种情况下,您必须修改 signIn 函数以将标头设置到您的申请中(此标头会说明您是否已登录) 是这样的:

const signIng = async() =>{
...
    api.defaults.headers.someTokenName = token; //Here you can set something just to identify that there is something into someTokenName or your JWT token
...
}

然后在你的 withAuth 组件中:

const WithAuth = (): JSX.Element => {
  // ... your component code
}

export const getServerSideProps: GetServerSideProps = async(ctx) => {
  const session = await ctx.req.headers['someTokenName'];

 if(!session){
   return{
    redirect:{
      destination: '/yourhomepage', //usually the login page
      permanent: false,
    }
   }
 }

 return{
  props: {
   authenticated: true 
  }
 }
}

这应该可以防止您的 Web 应用程序从未经身份验证闪烁到经过身份验证

这是一个typescript版本,您可以将允许的权限传递给 HOC 并与登录用户的现有权限进行比较。

export interface ProtectedComponentProps {
requiredPermission: string;
}

const ProtectedComponent: React.FC<ProtectedComponentProps> = (props) => {
const [isAuthorized, setIsAuthorized] = useState<boolean>();
useEffect(() => {
    const permissions = authService.getPermissions();
    setIsAuthorized(permissions.includes(props.requiredPermission))

}, []);
return (
    <>
        {isAuthorized ? props.children : <p>not authorized</p>}
    </>


);
}

export default ProtectedComponent;

并像这样使用它:

 <ProtectedComponent requiredPermission="permissionName">
      <SomeProtectedComponent />
 </ProtectedComponent>