参考自文章
Springboot+Vue前后端分离实现token登录验证和状态保存
1. 后端Springboot
2. 前端Vue
目录结构
image2.1 登录页的login方法:获取token并存储在localStorage中(view/login.vue)
login() {
// 从用户输入中获取name和password,从user.js中引入封装的Login方法
Login(this.users.name,this.users.password).then(res => {
console.log(res)
// 请求失败
if(!res.data){
alert("用户名或密码错误");
return
}
const token = res.data.token;
const user = res.data.user;
/*存储到ls*/
localStorage.setItem('eleToken',token);
/*解析token中的信息*/
const decoded = jwt(token);
/*存储至vuex*/
this.$store.dispatch("setLogin",!this.isEmpty(decoded)) //decoded空,函数返回真,取反假
this.$store.dispatch("setUser",user)
/*跳转*/
this.$router.push('/home');
})
.catch(err => {
console.log(err)
});
},
isEmpty(value){
return(
value ===undefined || value ===null ||
(typeof value === "object" && Object.keys(value).length ===0) ||
(typeof value ==="string" && value.trim().length ===0)
);
},
2.2 路由守卫判断是否存在token,存在时正常访问,不存在时要求登录(router/index.js)
/*路由守卫 根据登录获得token*/
router.beforeEach((to,from,next) =>{
const isLogin = localStorage.eleToken ? true :false ;
if(to.path ==="/login" || to.path ==="/register"){
next();
}else{
isLogin ? next() :next("/login") /*真跳转 假登录*/
}
})
2.3 axios请求拦截和响应拦截(network/request.js)
import axios from 'axios'
import { Loading } from 'element-ui'; /*elementUI的loading*/
import { Message } from 'element-ui'; /*elementUI消息提醒*/
import router from '../router/index';
let loading;
function startLoading () {
loading = Loading.service({ /*在需要调用时:*/
lock: true,
text: '拼命加载中...',
background: 'rgba(0,0,0,0,7)'
});
}
function endLoading () {
loading.close();
}
export function request(config){
const instance = axios.create({
baseURL:'http://localhost:8888/day07/',
timeout:5000
})
//请求拦截
instance.interceptors.request.use(config => {
//加载动画
//startLoading();
/*判断token存在 登录拦截*/
if(localStorage.eleToken){
/*设置统一的header*/
config.headers.Authorization = localStorage.eleToken;
}
return config;
},error => {
return Promise.reject(error);
});
//响应拦截
axios.interceptors.response.use(Response => {
//结束加载动画
//endLoading();
return Response;
},error => {
//错误提醒
//endLoading();
Message.error(error.response.data);
/*获取错误状态码*/
const { status } =error.response;
if(status == 401){
Message.error("token失效,重新登录");
/*清楚token*/
localStorage.removeItem('eleToken');
/*跳转登录*/
router.push('/login')
}
return Promise.reject(error);
})
// 发送真正网络请求并返回
return instance(config)
}
2.4 页面刷新时重新判断token是否存在或过期,并将需要数据保存到vuex中(App.vue)
<script>
import jwt from 'jwt-decode';
import {findOneUserById} from './network/user'
export default {
name:'App',
created(){ /*在根组件进行判断,否则刷新就没了*/
this.initData()
},
methods: {
// 有token时初始化数据
initData(){
if (localStorage.eleToken){
const decoded = jwt(localStorage.eleToken);
let _this = this;
// 需完善,其它组件初始化获取vuex中的user数据时,若请求未完成user为undefined
findOneUserById(decoded.aud).then(res => {
console.log(res)
// token已过期
if(res.data.code == 401){
/*存储至vuex*/
localStorage.removeItem('eleToken')
_this.$store.dispatch("setLogin",false)
}else{
_this.$store.dispatch("setUser",res.data)
/*存储至vuex*/
_this.$store.dispatch("setLogin",!this.isEmpty(decoded))
}
}).catch(err=>{
console.log(err)
})
}
},
isEmpty(value){
return(
value ===undefined || value ===null ||
(typeof value === "object" && Object.keys(value).length ===0) ||
(typeof value ==="string" && value.trim().length ===0)
);
}
}
}
</script>
2.5 vuex中保存登录状态和登录用户信息(store/index.js)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const types ={
SET_LOGIN: 'SET_LOGIN',
SET_USER: 'SET_USER',
};
export default new Vuex.Store({
state: {
isLogin:false,
user:{}
},
mutations: {
[types.SET_LOGIN](state,isLogin){ /*设置是否授权*/
if(isLogin) state.isLogin = isLogin;
else state.isLogin = false;
},
/*类型,参数*/
[types.SET_USER](state,user){
if (user) state.user = user;
else state.user = {};
},
},
actions: {
setLogin:( {commit},isLogin) =>{
commit(types.SET_LOGIN,isLogin);
},
setUser:({commit},user) =>{
commit(types.SET_USER,user);
}
},
modules: {
}
})
网友评论