我读到过授权应该由服务器端完成,而不仅仅是客户端。但是我看不清这是什么样子。下面是我目前为止的代码。
App.js
这显示了在呈现页面之前,它将通过RequireAuth组件。
import { useContext} from 'react'
import './style.scss'
import Register from './pages/Register/Register'
import TeacherLogin from './pages/Login/TeacherLogin/TeacherLogin'
import StudentLogin from './pages/Login/StudentLogin/StudentLogin'
import ForgotPassword from './pages/ForgotPassword/ForgotPassword'
import PageNotFound from './pages/PageNotFound/PageNotFound'
import Home from './pages/Home/Home'
import AccountType from './pages/AccountType/AccountType'
import Users from './pages/Students/Students'
import SOTW from './pages/SOTW/SOTW'
import Landing from './pages/Landing/Landing'
import Add from './pages/Add/Add'
import Test from './pages/Test/Test'
import Edit from './pages/Edit/Edit'
import ClassStats from './pages/ClassStats/ClassStats'
import {
BrowserRouter,
Routes,
Route,
} from "react-router-dom";
import { DarkModeContext } from './Hooks/context/darkModeContext'
import Profile from './StudentPages/Profile/Profile'
import RequireAuth from './components/RequireAuth/RequireAuth'
function App() {
const {darkMode} = useContext(DarkModeContext)
return (
<div className={`theme-${darkMode ? "dark" : "light"}`}>
<BrowserRouter>
<Routes>
<Route path='/' element={<Landing />} />
<Route path="/register" element={<Register/>}/>
<Route path="forgot-password" element={<ForgotPassword/>} />
<Route path="test" element={<Test/>} />
<Route path="/auth">
<Route index element={<AccountType/>} />
<Route path ="teacher" element={<TeacherLogin/>} />
<Route path="student" element={<StudentLogin/>} />
</Route>
<Route path="/auth/teacher" element={<RequireAuth allowedRoles={['teacher']}/>}>
<Route path='dashboard' element={<Home/>} />
<Route path="SOTW" element={<SOTW/>}/>
<Route path="users">
<Route index element={<Users />} />
<Route path="add" element={<Add title='Add Student' button='Add' />} />
<Route path="edit" element={<Edit title='Edit Student' button='Update' />} />
</Route>
</Route>
<Route path="auth/student" element={<RequireAuth allowedRoles={['student', 'teacher']}/>}>
<Route path='profile/:id' element={<Profile/>} />
</Route>
<Route path="*" element={<PageNotFound/>}/>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
要求授权
这是一个检查用户本地存储的组件。它可以工作,但是不安全。
import { Navigate, useLocation, Outlet } from 'react-router-dom';
import { AuthContext } from '../../Hooks/context/AuthContext';
import { useContext, useEffect, useState } from 'react';
import axios from 'axios';
const RequireAuth = ({ allowedRoles }) => {
const { testUser, setTestUser, user } = useContext(AuthContext);
const [statusAuth, setStatusAuth] = useState(false);
const location = useLocation();
console.log(user)
useEffect(() => {
const fetch = async () => {
const res = await axios.get('/api/auth/protected')
console.log(res) // THIS IS WHERE I AM STUCK. WHAT DO I DO HERE?
}
fetch()
},[])
return allowedRoles.includes(user?.role) ? (
<Outlet />
) : user ? (
<Navigate to="/unauthorised" state={{ from: location }} replace />
) : (
<Navigate to="/" state={{ from: location }} replace />
);
};
export default RequireAuth;
使用Node.js的后端代码
这是验证令牌代码,用于验证令牌并检查用户是否为“教师”。但是,这并不灵活。例如,如果某个页面只能由另一个“学生”用户查看,则该代码将不起作用,因为它将检查用户是否为“教师”角色。
import jwt from 'jsonwebtoken'
import { createError } from './error.js'
export const verifyToken = (req, res, next) => {
const token = req.headers.cookie.split('=')[1]
if (!token) {
return next(createError(401, "You are not authenticated!"));
}
jwt.verify(token, process.env.JWT, (err, user) => {
if (err) return next(createError(403, "Token is not valid!"));
req.user = user;
next();
});
};
export const verifyAdmin = (req, res, next) => {
verifyToken(req, res, () => {
if(req.user.role === 'teacher') {
next()
} else {
return next(createError(403, 'You are not authorised'))
}
})
}
型
路线
import express from 'express'
import {register, login, refreshToken, logout, protectedRoute} from '../Controllers/auth.js'
import { verifyToken, verifyAdmin } from '../verifyToken.js';
const router = express.Router();
//PROTECTED ROUTE
router.get("/protected", verifyAdmin, protectedRoute)
export default router
主计长
import mongoose from 'mongoose'
import Student from '../Models/student.js'
import bcrypt from 'bcrypt'
import { createError } from '../error.js'
import jwt from 'jsonwebtoken'
export const protectedRoute = async (req, res, next) => {
res.status(200).send('Success')
}
我已经到了验证令牌的阶段。我是否在每个页面请求到后端时都这样做,以确定用户是否可以实际查看该页面?
如果是,如何使require auth组件灵活地根据用户是否为以下用户进行重定向:学生,老师,行政人员还是其他人
2条答案
按热度按时间icomxhvb1#
我觉得我在这里作弊,但一个简单的安装jwt-decode解决了这个问题。
其实现包含在RequireAuth组件中,如下所示:
但是,仍然没有后端验证。是否需要?如果用户在登录时通过验证,并且JWT签名并交付,那么他们是否可以被信任访问其他路由?
任何指导都很好。
2lpgd9682#
这里有一个替代答案,我希望得到你的意见。
在这里,我通过POST方法将AllowedRoles传递到后端。
在后端,我解码JWT并获取用户的角色,然后检查它是否存在于授权角色中。
如果是,我发送一条成功消息。
在前端,如果res成功,那么我设置状态:允许(真)和正在检查(假)。
这看起来像我想要的那样工作,但我不确定这是最好的做法。任何意见都将非常感谢。
后端代码