实现思路:封装一个高阶组件,路由鉴权高阶组件,实现未登录拦截,并跳转到登录页面,判断是否有token,如果有,就返回相对应的路由,如果没有就重定向到登录login页面
步骤:
1.在router文件中封装AuthRouter.js文件
2.在router.js中引入封装的这个高阶组件
3.登录页面实现
高阶组件的封装
router/AuthRouter.js
// 路由守卫
// 判断token是否存在(如果存在跳转主页,如果不存在跳转登录页面)
import { Navigate } from 'react-router-dom'
// 获取token方法
const getToken = () => {
return localStorage.getItem('token')
}
// 创建一告诫组件,高阶组件就是把一个组件当作另一个组件的参数传入,然后通过判断 返回新的组件
// 下面的authRouter 就是一个高阶组件
function AuthRouter({ children }) {
// 获取token
const token = getToken()
console.log(token, 'aaaa')
// 判断token是否存在 存在直接渲染主页面
if (token) {
return <>{children}</>
} else {
return <Navigate to={'/login'}></Navigate> //没有token跳转登录页面
}
}
export { AuthRouter }
router/index.js
import Layout from "../pages/layout";
import Cloud from "../pages/cloud/cloud";
import State from "../pages/state/state";
import Setting from "../pages/setting/setting";
import Home from "../pages/home/home";
import Field from '../pages/cloud/field/field'
import Detail from '../pages/detail/detail'
import Cart from '../pages/cart/cart'
import Login from '../pages/login/login'
import { Navigate } from "react-router-dom";
import { AuthRouter } from "./AuthRouter"; //引入高阶组件
const routerList = [
{
path: '/', element: <Navigate to='/layout/home'></Navigate>
},
{
path: 'layout', element: <AuthRouter><Layout></Layout></AuthRouter>, children: [
{ path: 'home', element: <Home></Home> },
{ path: 'cloud', element: <Cloud></Cloud> },
{ path: 'field', element: <Field></Field> },
{ path: 'state', element: <State></State> },
{ path: 'setting', element: <Setting></Setting> },
{ path: 'detail', element: <Detail></Detail> },
{ path: 'cart', element: <Cart></Cart> }
]
},
{
path: 'login', element: <Login></Login>
}
]
export default routerList
登录页面代码
import React from 'react'
import './style.css'
import axios from '../../server/request'
import { useNavigate } from 'react-router-dom'
import { Button, Checkbox, Form, Input } from 'antd';
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
export default function Login() {
const nav = useNavigate()
async function onFinish(values) {
const data = await axios.post('/login', values)
if (data.code == 200) {
localStorage.setItem('token', JSON.stringify(data.token))
nav('/layout/home')
}
};
return (
<div className='login'>
<div className='box'>
<Form
name="basic"
labelCol={{
span: 8,
}}
wrapperCol={{
span: 16,
}}
style={{
maxWidth: 600,
}}
initialValues={{
remember: true,
}}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<Form.Item
label="用户名"
name="username"
rules={[
{
pattern: /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1589]))\d{8}$/,
required: true,
message: '请输入正确的手机号',
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="密码"
name="password"
rules={[
{
pattern: /^[a-z][0-9]{5}$/,
required: true,
message: 'Please input your password!',
},
]}
>
<Input.Password />
</Form.Item>
<Form.Item
name="remember"
valuePropName="checked"
wrapperCol={{
offset: 8,
span: 16,
}}
>
<Checkbox>Remember me</Checkbox>
</Form.Item>
<Form.Item
wrapperCol={{
offset: 8,
span: 16,
}}
>
<Button type="primary" htmlType="submit">
登录
</Button>
</Form.Item>
</Form>
</div>
</div>
)
}
后端代码
下载 jsonwebtoken
引入:var jwt = require(‘jsonwebtoken’)
router.post('/login', async (req, res) => {
let username = req.body.username
let password = req.body.password
console.log(username, password)
if (!username || !password) {
res.send({
code: 400,
msg: '账号和密码不能为空'
})
}
let token = 'Bearer ' + jwt.sign({ username, password }, "asdf", { expiresIn: 60 * 60 * 2 })
let user = await userModel.create({ username, password })
if (!user) {
return res.send({
code: 400,
msg: '该用户不存在'
})
}
user = await userModel.findOne({ username, password })
// console.log();
console.log("user:0", user)
res.send({
code: 200,
msg: '登录成功',
user,
token
})
})
router.get('/getlist', async (req, res) => {
let data = await shopModel.find()
res.send({
code: 200,
data: data
})
})