我试图在我的react应用程序中实现RBAC,我使用nodejs作为后端,它工作得很好,在react中我使用vite和react-router-dom v6。为了简单起见,我决定将从服务器检索到的令牌和角色存储在会话存储中。我在我的应用程序中有2个角色,“基本”和“管理员”,在我成功登录后,我根据从我的服务器中检索到的角色重定向。我有一个HOC作为“中间件”,在我的路由布局中检查角色权限。重定向工作正常,但是,当我测试它时,我得到了两个角色的空页面,它们都应该呈现一个简单的h1标记。我在实现中遗漏了什么或做错了什么?
登录页面:
import {useState} from 'react'
import { useNavigate } from 'react-router-dom';
import axios from 'axios';
const Login = () => {
const navigate = useNavigate()
const [input, setInput] = useState({
email:"",
password:""
})
const handleInputChange = (e) => {
const {name, value} = e.target;
setInput((prev) => ({
...prev, [name]:value
}))
};
const handleSubmit = async (e) => {
e.preventDefault();
console.log(input);
const url = "http://localhost:8080/auth/login";
try {
const response = await axios.post(`${url}`,
input,
{headers:{
'content-type':'application/json'
}}
);
console.log(response);
if(response.status === 200) {
console.log("ok");
const token = response.data.token;
const role = response.data.role
console.log({"token":token, "role":role})
sessionStorage.setItem('token', token);
sessionStorage.setItem('role', role);
if(role === "admin"){
navigate('/admin');
} else if( role === "basic") {
navigate('/basic');
} else {
navigate('/login');
}
}
} catch(error) {
console.log({"error":error.response})
}
}
return (
<div>
<h1>Log In</h1>
<form onSubmit={handleSubmit}>
<p>email:</p>
<input type="text" name="email" value={input.email} onChange={handleInputChange}/>
<p>password:</p>
<input type="text" name="password" value={input.password} onChange={handleInputChange}/><br/>
<button type='submit'>Login</button>
</form>
</div>
)
}
export default Login
app.js文件中的路由器布局:
import { } from 'react'
import './App.css'
import { Route, Routes } from 'react-router'
import Access from './Auth/Access'
import Home from './pages/Home'
import Login from './pages/Login'
import Signup from './pages/Signup'
import Admin from './pages/Admin'
import Basic from './pages/Basic'
import { Error } from './pages/Error'
function App() {
return (
<div>
<Routes>
<Route path='/' element={<Home/>}/>
<Route path='/login' element={<Login/>}/>
<Route path='/signup' element={<Signup/>}/>
<Route path='/basic' element={<Access role={'basic'}> <Basic/></Access>}/>
<Route path='/admin' element={<Access role={'admin'}><Admin/></Access>}/>
<Route path='*' element={<Error/>}/>
</Routes>
</div>
)
}
export default App
我的HOC检查路由中的角色,名称为Access:
import { Navigate,Outlet } from "react-router-dom";
const Access = ({ role }) => {
const userRole = sessionStorage.getItem("role");
const token = sessionStorage.getItem('token');
if (!token || (role && role !== userRole)) {
// Redirect to login if token is not available or user role doesn't match
return <Navigate to="/login" replace />;
}
// User has the required role or no role is specified, render the nested components
return <Outlet />;
};
export default Access
我希望这两个页面都使用简单的h1标记呈现,基于登录的角色重定向。
Admin page:
/* eslint-disable no-unused-vars */
import React from "react"
const Admin = () => {
return (
<div>wecome to admin page</div>
)
}
export default Admin
// eslint-disable-next-line no-unused-vars
import React from 'react'
const Basic = () => {
return (
<div>welcome to basic page</div>
)
}
export default Basic
1条答案
按热度按时间3zwjbxry1#
经过大量的调整,我想我终于能够解决这个问题了。我创建了一个HOC来接受一个角色,然后有条件地导航当前登录的。
这是我的解决方案,但我会保持这个职位开放的情况下,有人会有一个更好的解决办法,然后我的…
让我们从app.js文件中的路由器布局开始:
正如您所看到的,我的HOC被命名为“Access”,它接受一个角色作为 prop 。
下面是“访问”组件:请注意:这是一个简单的验证,因为我想让事情尽可能简单。
我的登录组件保持不变,所以没有变化,我添加到子页面的“基本”用户,所以当我可以使用“标签”布局,以导航之间的这2页。
所以这里是我的“基本”页面,请注意,其他页面有简单的h1标签呈现,所以我没有在这里添加它们..
基本页面: