react 登录访问控制 / react登录鉴权 / react
从个人中心页面中登录
登录成功后
点击上海,跳转 /citylist路由,此路由需要鉴权, 判断用户是否登录
有token,就能跳转/citylist, 否者先跳转到/login,登录成功后再跳转/citylist
功能: 如登录后才能获取个人资料;
方案: 登录后才能操作的功能使用axios拦截器 统一添加请求头authorization
页面:如登录后才能访问个人详情页,个人收藏页;
方案: 登录后才能访问的页面通过封装鉴权路由组件,react中没有直接提供,需要自己手动封装来实现登录访问控制, 类似于vue中-路由守卫
功能: 在axios中设置token请求头,通过某些功能的调用,这些调用一定是登录成功后返回的token的情况下进行, 否则就跳转到登录页去登录
import axios from 'axios'
import { BASE_URL } from './url'
// import {HashRouter} from 'react-router-dom' //如果使用的是hash路由类型,使用这个
// const router = new HashRouter()
import {BrowserRouter} from 'react-router-dom'
const router = new BrowserRouter()
const API = axios.create({
baseURL: BASE_URL
})
// 添加请求拦截器
API.interceptors.request.use(config=>{
const { url } = config;
// startsWith() ---以什么开头; 这两个请求路径不需要token
if(!url.startsWith('/login') || !url.startsWith('/register')){
//当请求路径不是这两个的时候, 添加token请求头
config.headers.Authorization = localStorage.getItem('token');
}
return config
})
API.interceptors.response.use(response => {
const { status } = response.data; //这里的response数据结构不一样,直接打印出来看,参照后端返回的结果
if(status === 400 || status === 401 || status === 402 || 403){
localStorage.removeItem('token');
//当token超时or失效 403账号无权限的时候直接跳转到/login页重新登录
router.history.push('/login')
}
return response
})
export { API }
页面: 封装鉴权路由组件:
react鉴权路由示例: https://reactrouter.com/web/example/auth-workflow
1.在components创建AuthRoute/index.js文件
2.创建 AuthRoute组件并导出
3.在 AuthRoute组件中返回 Route组件(在Route基础上做一层包装,用于实现自定义功能)
4.给Route组件,添加render方法, 指定该组件要渲染的内容(类似component属性)
5.在render方法中, 调用localStorage中的token判断是否登录
6.如登录: 就渲染当前组件(通过参数component获取到要渲染的组件,需要重命名)
7.如没登录: 就重定向到登录页面,并且指定登录成功后要跳转到的页面路径
8.将AuthRoute组件接收到的props原样传递给Route组件(保证与Route组件使用方式相同)
9.使用 AuthRoute组件配置路由规则, 验证能否实现页面的登录访问控制
10.修改登录页面,在登录成功后,判断是否需要有没有需要跳转到用于想要的页面(通过props.location.state是否有值;
有值说明就是从登录鉴权那边过来的),跳转到from.pathname指定的页面;
没有值说明,不是从登录鉴权组件来的,就是在登录页登录成功后,直接调用history.go(-1)返回上一页即可
已经封装好AuthRoute组件了,可直接使用↓
import React from 'react';
import { Route,Redirect } from 'react-router-dom';
//使用时: <AuthRoute path="" component={...} />
const AuthRoute = ( {component: Component, ...rest} )=>{ //标签传入的参数compoennt,并重命名Component
return <Route {...rest} render={props=>{
let isLogin = localStorage.getItem('token');
if(isLogin){
return <Component {...props}/> //如果登录了就渲染组件
}else{
//如没登录,就重定向到登录页面,并且通过属性state指定登录成功后要跳转回之前的页面路径
return <Redirect to={ {pathname:'/login',state:{from: props.location}} }/>
}
}}></Route>
}
export default AuthRoute;
在App.js中↓,需要鉴权的页面,通过AuthRoute替换原本的Route来鉴权
import React, { Component } from 'react'
import { BrowserRouter as Router, Route, Redirect} from 'react-router-dom'
import Home from './pages/Home'
import CityList from './pages/CityList'
import Login from './pages/Login'
import AuthRoute from './components/AuthRoute'
export default class App extends Component {
render() {
return (
<Router>
<Route path="/home" component={Home}/>
{/* <Route path="/citylist" component={CityList}/> */}
<AuthRoute path="/citylist" component={CityList}/>
<Route path="/login" component={Login}/>
<Redirect to="/home"/>
</Router>
)
}
}
login.js中,登录成功后跳转回进来前的页面
handleSubmit = async(e)=>{ 登录这里我没有做账号验证哦!!
let {username, password} = this.state;
e.preventDefault();
const res = {
data:{
status:200,
token:'asdsdfdfsdfssdf',
message:'success'
}
}
if(res.data.status === 200){
Toast.success('登录成功', 1);
localStorage.setItem('token', res.data.token);
if(!this.props.location.state){ //没有值就是普通跳转进登录页,直接返回即可
this.props.history.go(-1);
}else{
//有值通过鉴权路由传过来的from.pathname跳转回去
this.props.history.replace(this.props.location.state.from.pathname)
}
}else{
Toast.fail(res.data.message, 1);
}
}