reactjs 如何在NextJS应用程序中处理公共和私人路线?

camsedfj  于 2023-01-05  发布在  React
关注(0)|答案(6)|浏览(128)

我正在开发一个应用程序,我们有公共和管理路线,在我们过去的CRA应用程序中,我们使用了自定义路线元素,但我们在nextjs中没有thins...我们有很多公共页面,我们有20个私人页面/路线。
在nextjs中处理受保护的autenticated路由和公共路由的最好方法是什么?
太感谢了!最好的

zmeyuzjn

zmeyuzjn1#

我个人一直在使用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);

如果需要,您可以使用Auth HOC扩展角色检查,如public、regular user和admin。

nnvyjq4y

nnvyjq4y2#

非常感谢@AleXius您的回答!我已经混合了您的解决方案和这个great article为那些谁想要使用这个特设与 typescript :

import { NextComponentType } from "next";

function withAuth<T>(Component: NextComponentType<T>) {
  const Auth = (props: T) => {
    // 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;
j5fpnvbx

j5fpnvbx3#

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

对于静态生成的页面:

您可以像@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中处理它。

d8tt03nd

d8tt03nd4#

除了使用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
...
}

然后在yout中使用Auth组件:

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应用程序从未经身份验证的状态切换到已验证的状态

qv7cva1a

qv7cva1a5#

下面是一个如何在Next.js中创建私有路由的示例:
首先,创建一个高阶组件(HOC),它将在呈现受保护的路由组件之前检查用户是否经过身份验证:

import { useEffect, useState } from 'react';
import Router from 'next/router';

const withAuth = (WrappedComponent) => {
const WithAuth = (props) => {
    const [loading, setLoading] = useState(true);
    const [user, setUser] = useState(null);

    useEffect(() => {
        // Fetch user data here and set it using setUser
        // For example:
        // setUser(fetchUserData());

        setLoading(false);
    }, []);

    if (loading) {
        return <div>Loading...</div>;
    }

    if (!user) {
        Router.push('/login');
        return null;
    }

    return <WrappedComponent {...props} />;
};

WithAuth.getInitialProps = async (ctx) => {
    const wrappedComponentInitialProps = WrappedComponent.getInitialProps
        ? await WrappedComponent.getInitialProps(ctx)
        : {};

       return { ...wrappedComponentInitialProps };
    };

   return WithAuth;
};

export default withAuth;

然后,使用withAuth HOC Package 受保护的路由组件:

import withAuth from '../hoc/withAuth';

const ProtectedRoute = (props) => {
  return <div>This is a protected route</div>;
};

export default withAuth(ProtectedRoute);

最后,在Next.js应用中使用受保护的路由组件,就像使用其他路由一样:

import ProtectedRoute from '../components/ProtectedRoute';

const Home = () => {
  return (
    <div>
      <ProtectedRoute />
    </div>
  );
};

export default Home;

这只是在Next.js中实现私有路由的一种方法,但它应该给予您了解如何实现私有路由。

jxct1oxe

jxct1oxe6#

这是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>

相关问题