react 登录访问控制 / react登录鉴权 / react

2021-05-11  本文已影响0人  Peter_2B
从个人中心页面中登录
登录成功后
点击上海,跳转 /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);
        }
    }
上一篇 下一篇

猜你喜欢

热点阅读