仓库地址:https://gitee.com/zhouyunfang/react-project/tree/formAuthenticated/
目录
存储token
解析token
解决页面刷新,数据消失问题
当前目录:
login.js
import React, { Component } from 'react'
// 实现ui组件和数据连接
import {connect } from 'react-redux'
// 引入redux中的authAtcion.js/loginUser定义的方法
import {loginUser} from '../../actions/authAchtions'
class Login extends Component {
constructor(props){
super(props)
this.state={
password:'',
email:'',
errors:{}
}
}
onSubmit(e){
e.preventDefault()
const newUser ={
password:this.state.password,
email:this.state.email
}
// 点击登录的时候把数据存入redux的authActions.js中
this.props.loginUser(newUser)
}
})
// 将返回的状态转换成属性
const mapStateToProps = (state) =>({
// auth 在reducers下定义的一大的reducers
// auth :state.auth,
errors:state.errors
})
export default connect(mapStateToProps,{loginUser})(Login) ;
在点击登录的时候,我的请求方式用redux管理起来了;
authActions.js
// 用户发送请求的处理方法会在这里执行
import axios from 'axios';
// 引入设置token方法
import setAuthToken from '../utils/setAuthToken.js'
// 引入type类型
import { GET_ERRORS } from './types'
// 登录信息
export const loginUser = (userData,history) => dispatch =>{
axios.post('/api/users/login',userData)
.then(res =>{//对返回的token进行解构,并存储
const {token } = res.data;
localStorage.setItem('jwToken',token)
//设置axios的headers token
setAuthToken(token)
}).catch(err =>{
// 在登录息错误的时候用dispatch把信息返回回去
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
})
}
utils.AuthToken.js
import axios from "axios";
const setAuthToken = token =>{
if(token){
// token存在设置header,因为后续每个请求都需要
axios.defaults.headers.common['Authorization'] = token ;
}else{
// 没有token就移除
delete axios.defaults.headers.common['Authorization'];
}
}
export default setAuthToken ;
安装模块:
npm i jwt-decode
在authActions.js页面引入:
// 用户发送请求的处理方法会在这里执行
import axios from 'axios';
// 引入解析token方法
import jwt_decode from 'jwt-decode'
// 引入设置token方法
import setAuthToken from '../utils/setAuthToken.js'
// 引入type类型
import { GET_ERRORS ,SET_CURRENT_USER} from './types'
// 登录信息
export const loginUser = (userData,history) => dispatch =>{
axios.post('/api/users/login',userData)
.then(res =>{//对返回的token进行解构,并存储
const {token } = res.data;
localStorage.setItem('jwToken',token)
//设置axios的headers token
setAuthToken(token)
// 解析token
const decoded = jwt_decode(token)
// console.log(decoded)
// 解析之后用dispatch分发
dispatch(setCurrentUser(decoded))
}).catch(err =>{
// 在登录息错误的时候用dispatch把信息返回回去
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
})
}
export const setCurrentUser = decoded =>{
// 设置type,下一步return到reducers/authReducer.js中
return{
type:SET_CURRENT_USER,
payload:decoded
}
}
reducers/authReducer.js页面
// 对authAchtions.js返回回来的定义type类型进行判断成功后再把用户数据返回至组件
import { SET_CURRENT_USER } from '../actions/types';
import isEmpty from '../validation/is-empty'
const initialState ={
isAuthenticated:false,
user:{}
}
// reducer接受两个参数,State,和action 作为参数,返回一个新的state
export default function(state = initialState,action){
// 对传过来的type进行配置然后返回
switch (action.type){
case SET_CURRENT_USER :
return {//如果type类型匹配上就把最新的state赋给initialState中对应的属性,再返回至来源组件(login.js)
...state,//可能返回多个,所以用展开运算符
user:action.payload,//把action下的payload更新至user
isAuthenticated:!isEmpty(action.payload),//确认授权,为防止payload是空值所以还在判断一下
}
default :
return state;
}
}
validation/is-empty.js
页面写判断用户登陆的是否为空值
// 判断登录的值是否为空值
const isEmpty = value => {
return value === undefined || value === null ||
(typeof value === "object" && Object.keys(value).length === 0) ||
(typeof value === "string" && value.trim().length === 0)
}
module.exports = isEmpty;
在app.js中再请求一次然后赋值
app.js
import store from './store';
import setAuthToken from './utils/setAuthToken'
import jwt_decode from 'jwt-decode'
import { setCurrentUser } from './actions/authAchtions';
if(localStorage.jwToken){
console.log(11)
setAuthToken(localStorage.jwToken)
// 解析token
const decoded =jwt_decode(localStorage.jwToken)
store.dispatch(setCurrentUser(decoded))
// 检测token过期
// 获取当前时间
const currentTime= Date.now() / 1000;//由毫秒转成秒
console.log(decoded)
console.log(currentTime)
// 判断当前时间是否大于token中的exp时间;如果大于是为过期
if(decoded.exp < currentTime){
// 过期
store.dispatch(logoutUser())
// 退出后再跳转页面
window.location.href = "/login";
}
}