退出登录
在后台开发逻辑,所以关于登录的处理建议大家都在store去完成。不要在外面额外定义操作。比如:登录,获取用户信息,获取token,获取角色,获取权限都在这里。包括退出登录。
1: 修改store/modules/user.js
- 在actions 定义异步方法去请求服务器进行服务器退出。这里会调用一个服务器的退出接口,并且调用mutations的清除state状态管理的方法
- 在mutations定义清除状态管理的方法。
- 清除完毕,使用router重定向到登录页面。
为什么一定要这做:因为state的数据只能通过mutations进行管理和操作。
01、定义服务器接口
/**
* 退出登录
* @param request
* @return
*/
@PostMapping("/login/logout")
@PugDoc(name = "退出登录")
public String logout(HttpServletRequest request) {
// 通过请求头获取
String token = jwtService.getToken(request);
String userId = jwtService.getTokenUserId(request);
Vsserts.isEmptyEx(token, AdminUserResultEnum.TOKEN_NOT_FOUND);
Vsserts.isNullEx(userId, AdminUserResultEnum.USER_NAME_NOT_EMPTY);
// 删除下线的uuid
String tokenUuidKey = USER_LOGIN_LOGOUT_KEY + userId;
stringRedisTemplate.delete(tokenUuidKey);
// 删除续期redis的key
String tokenKey = USER_LOGIN_TOKEN_KEY + token;
stringRedisTemplate.delete(tokenKey);
// 加黑名单,防止下次使用,它可能是在刚刚生成的时候就退出了。退出逻辑一定力求不管你token有效还是过期都应该后续不能在使用
jwtBlackService.addBlackList(token);
// 退出登录
return "success";
}
02、定义退出接口调用
services/LoginService.js定义退出接口
import request from '@/utils/request'
export default {
/**
* 登录逻辑
* @param {} user
* @returns
*/
toLogin(user) {
return request.post("/login/toLogin", user);
},
/**
* 退出逻辑
* @returns
*/
toLogout() {
return request.post("/login/logout");
}
}
03、定义store管理退出功能
在store/modules/user.js中定义actions和mutations的相关退出逻辑,如下:
import loginService from '@/services/login/LoginService';
export default {
namespaced: true,
// 定义全局状态管理的响应式数据
state() {
return {
// 管理的用户对象信息
userId: "",
username: "",
avatar: "",
token: "",
roleList: [],
permissionList: []
}
},
// 定义修改状态管理的方法
// 结论:修改state的全局状态数据只能通过mutations的方法进行修改。
// 调用通过:store.commit方法执行和调用
mutations: {
// 同步state中用户的信息
toggleUser(state, serverUserData) {
state.token = serverUserData.token;
state.tokenUuid = serverUserData.tokenUuid;
state.userId = serverUserData.user.id;
state.username = serverUserData.user.username;
state.avatar = serverUserData.avatar;
state.roleList = [{ name: "管理员" }];
state.permissionList = [{ code: "-1" }];
},
// 清除状态
clearUser(state) {
state.userId = "";
state.account = "";
state.avatar = "";
state.token = "";
state.roleList = [];
state.permissionList = [];
// 这里记得把持久化的状态管理清除。这里不执行也可以
//localStorage.removeItem("pug-admin-web-vuex");
}
},
// 异步修改状态的的方法
// 注意:actions定义的方式,不能直接修改state的状态数据
// 只能通过context.commit去条件mutations的方法去修改state的数据。它是一个间接的方式
// 调用通过:store.dispatch方法执行和调用
actions: {
async toLogout(context) {
//1: 异步请求去执行服务器退出操作
//2: 执行页面状态清空
try {
// 清楚本地状态和缓存相关信息
context.commit("clearUser");
// 获取服务端的返回操作
var serverResponse = await loginService.toLogout();
// 返回,这里是promise
return Promise.resolve(serverResponse);
} catch (err) {
// 为什么不在这里处理呢,因为在这里没有办法和页面进行交互。
// 抛出给谁用,肯定是具体调用者去捕获,和java异常抛出一模一样的概念呢
return Promise.reject(err);
}
},
// 从登录以后的axios请求中获取serverUserData
async toLogin(context, loginUserData) {
try {
// 发起登录请求
const serverResponse = await loginService.toLogin(loginUserData);
// 通过context.commit去修改mutations中toggleUser去同步state数据
context.commit("toggleUser", serverResponse.data);
// 返回,这里是promise
return Promise.resolve(serverResponse);
} catch (err) {
// 为什么不在这里处理呢,因为在这里没有办法和页面进行交互。
return Promise.reject(err);
}
}
},
// 对state数据的改造和加工处理。给未来的页面和组件进行调用。
// 从而达到一个封装的目录 computed
getters: {
// 组装一个角色信息返回
getRoleName(state) {
return state.roleList.map(role => role.name).join(",");
},
// 获取权限
getPermissions(state) {
return state.permissionList.map(role => role.code);
},
// 获取用户ID
getUserId(state) {
return state.userId;
},
// 获取token
getToken(state) {
return state.token;
},
// 获取tokenUuid 用于同一账号挤下线
// 因为你每次登录都会产生新的uuid。所以旧的就被你新挤掉
getTokenUuid(state) {
return state.tokenUuid;
},
// 判断是否登录
isLogin(state) {
return state.userId != "";
}
}
}
03、调用退出功能接口
<template>
<h1>后台首页</h1>
<p>登录的信息是:{{store.state.user.username}}</p>
<button @click="handleLogout">退出</button>
</template>
<script setup>
import { useStore} from 'vuex';
import { useRouter} from 'vue-router';
const store = useStore();
const router = useRouter();
const handleLogout = ()=>{
if(confirm("你确定退出登录吗?")){
store.dispatch("user/toLogout").then(logoutRes=>{
// 这里肯定是退出成功才会进入
router.push("/toLogin");
});
}
}
</script>