如何将用户类型的路由保护添加到具有 React 前端和 JWT 的 Laravel Web 应用程序?

Posted

技术标签:

【中文标题】如何将用户类型的路由保护添加到具有 React 前端和 JWT 的 Laravel Web 应用程序?【英文标题】:How do I add route protection by user type to a Laravel web application with React frontend and JWT? 【发布时间】:2019-11-28 22:27:24 【问题描述】:

我正在制作一个 Laravel 应用程序,让教师可以为学生管理测试。我正在使用 React 前端,并且正在使用 JWT 对用户进行身份验证。我想按用户类型保护路线(例如,教师可以访问页面进行测试,而学生不能)。

通常情况下,我可以做类似的事情

Route::middleware('jwt.auth')->get('users', function () 
    return auth('api')->user();
);

但我将所有内容路由到我的welcome.blade.php 并使用 React Router 渲染路由。这就是我路由所有内容的方式:

Route::any('all', function () 
    return view('welcome');
)->where(['all' => '.*']);

我这样做是因为我注意到当我刷新非根路由时会出现 404 错误(例如,如果我刷新 /teacher-home 上的页面,我曾经得到 404)。我的问题是如何按用户类​​型保护我的路线,除了 /signin 和 /signup (希望这些不受保护,以便任何人都可以访问它们)?

这是我的用户登录代码:

public function login() 
        // get email and password from request
        $credentials = request(['email', 'password']);

        // try to auth and get the token using api authentication
        if (!$token = auth('api')->attempt($credentials)) 
            // if the credentials are wrong we send an unauthorized error in json format
            return response()->json(['error' => 'Unauthorized'], 401);
        
        return response()->json([
            'token' => $token,
            'type' => 'bearer',
            'expires' => auth('api')->factory()->getTTL() * 60, // time to expiration

        ]);

这是我的用户迁移:

Schema::create('users', function (Blueprint $table) 
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->enum('user_type', ['teacher', 'student']);
            $table->rememberToken();
            $table->timestamps();
        );

这是我所有路线的列表

<Route exact path='/' render=(pathName) => <Redirect to='/teacher-home'/>/>
                        <Route exact path='/teacher-question-repo' render=(pathName) => <QuestionRepo path=pathName/>/>
                        <Route exact path='/teacher-home' render=(pathName) => <TeacherHome path=pathName/>/>
                        <Route exact path='/teacher-monitor' render=(pathName) => <TeacherMonitor path=pathName/>/>
                        <Route exact path='/teacher-tests' render=pathName => <TestRepo path=pathName/>/>
                        <Route exact path='/student-home' component=StudentHome/>
                        <Route exact path='/student-test' render=() => <StudentTest testName="Normal Curves"/>/>
                        <Route exact path='/edit-question/:item_id' component=EditQuestion/>
                        <Route exact path='/teacher-tests/new-test' render=(pathName) => <TestForm path=pathName/>/>
                        <Route exact path='/teacher-tests/edit-test/:test_id' render=(pathName) => <TestForm path=pathName/>/>
                        <Route exact path='/signin' component=SignIn/>
                        <Route exact path='/signup' component=SignUp/>

【问题讨论】:

【参考方案1】:

由于 react 正在处理您的路由,因此您不应在服务器端执行身份验证。

您可以使用自定义路由组件并在其中添加您的身份验证逻辑。看看下面的教程:https://tylermcginnis.com/react-router-protected-routes-authentication/

【讨论】:

您不能仅依靠 react 来保护您的信息。您还需要保护后端的路由。否则,您可以直接通过 http 请求访问路由并获取所需的所有信息。这就是 JWT 的全部意义所在。您将令牌传递给后端以验证您的用户,而不是每次都查询数据库。但是您绝对必须在服务器端执行身份验证。 React 无法保护您的敏感信息。 也许我的回答不是很清楚,但你肯定需要保护反应组件调用的 API 路由。 问题要求的是一种保护反应路线的方法。张贴者使用了一个仅呈现反应路由器视图(即没有数据)的后备路由。

以上是关于如何将用户类型的路由保护添加到具有 React 前端和 JWT 的 Laravel Web 应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

React Typescript - 在路由中传递时如何将类型添加到 location.state

如何在 react redux 中添加受保护的路由

React-Router-Dom v6 保护路由

使用 react router dom v6 保护路由 渲染没有返回任何内容

页面未呈现;在 react-router-dom 中使用受保护的路由将道具传递给孩子时

如何将 jwt 令牌发送到 node.js 中的受保护路由