登陆后,从后台加载出当前登录用户的信息
1 登录信息实体类
package com.grm.entity;
import java.io.Serializable;
import java.util.List;
/**
* 登录用户信息(用户名+头像,菜单列表)
*
* @author gaorimao
* @date 2022/02/10
*/
public class LoginUserInfo implements Serializable {
/**
* 用户名
*/
private String username;
/**
* 头像
*/
private String avatar;
/**
* 系统菜单
*/
private List<SysMenu> sysMenus;
/**
* 用户所拥有的url权限、按钮权限
*/
private List<String> perms;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public List<SysMenu> getSysMenus() {
return sysMenus;
}
public void setSysMenus(List<SysMenu> sysMenus) {
this.sysMenus = sysMenus;
}
public List<String> getPerms() {
return perms;
}
public void setPerms(List<String> perms) {
this.perms = perms;
}
}
2 首页加载Controller
package com.grm.controller;
import com.grm.common.Result;
import com.grm.entity.LoginUserInfo;
import com.grm.service.IndexService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 首页控制器,加载用户信息和所拥有的菜单列表
*
* @author gaorimao
* @date 2022/02/10
*/
@Slf4j
@RestController
public class IndexController {
@Autowired
private IndexService indexService;
@GetMapping("/getLoginUserInfo")
public Result getLoginUserInfo() {
LoginUserInfo loginUserInfo = indexService.getLoginUserInfo();
return Result.success("加载登录用户信息成功!", loginUserInfo);
}
}
3 IndexSerivce
package com.grm.service;
import com.grm.entity.LoginUserInfo;
import com.grm.entity.SysMenu;
import com.grm.security.details.LoginUser;
import com.grm.util.RedisUtil;
import com.grm.util.SecurityUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 首页逻辑(获取登录用户信息和用户所拥有的菜单信息)
*
* @author gaorimao
* @date 2022/02/11
*/
@Service
public class IndexService {
@Autowired
private RedisUtil redisUtil;
@Autowired
private SecurityUtils securityUtils;
@Autowired
private SysMenuService sysMenuService;
public LoginUserInfo getLoginUserInfo() {
// 1. 获取当前登录用户
LoginUser loginUser = securityUtils.getLoginUser();
LoginUserInfo loginUserInfo;
// 从缓存中获取当前登录用户信息
Object loginUserInfoObj = redisUtil.get("LoginUserInfo:" + loginUser.getUsername());
if (!ObjectUtils.isEmpty(loginUserInfoObj)) {
// 从缓存中拿
loginUserInfo = (LoginUserInfo) loginUserInfoObj;
} else {
// 从DB中拿
loginUserInfo = queryLoginUserInfoByDb(loginUser);
// 存入缓存一份
redisUtil.set("LoginUserInfo:" + loginUser.getUsername(), loginUserInfo, 60 * 60 * 24 * 7);
}
return loginUserInfo;
}
/**
* 从数据库查询登录用户信息
*
* @param loginUser 登录用户
* @return {@link LoginUserInfo}
*/
private LoginUserInfo queryLoginUserInfoByDb(LoginUser loginUser) {
// 1.获取用户头像
String avatar = loginUser.getAvatar();
// 2.获取用户菜单
List<SysMenu> sysMenus = getSysMenusByUserId(loginUser.getUserId());
List<SysMenu> sysMenuTree = sysMenuService.buildTree(sysMenus);
// 3.获取用户权限
List<String> perms = getPermsByUserId(sysMenus);
LoginUserInfo loginUserInfo = new LoginUserInfo();
loginUserInfo.setUsername(loginUser.getUsername());
loginUserInfo.setAvatar(avatar);
loginUserInfo.setSysMenus(sysMenuTree);
loginUserInfo.setPerms(perms);
return loginUserInfo;
}
/**
* 根据用户id获取用户所具有的权限
*
* @param sysMenus 用户所拥有的菜单
* @return {@link List}<{@link String}>
*/
private List<String> getPermsByUserId(List<SysMenu> sysMenus) {
List<String> perms = new ArrayList<>();
if(ObjectUtils.isNotEmpty(sysMenus)){
for (SysMenu sysMenu : sysMenus){
if(ObjectUtils.isNotEmpty(sysMenu.getPath())){
perms.add(sysMenu.getPath());
}
if(ObjectUtils.isNotEmpty(sysMenu.getPerms())){
perms.add(sysMenu.getPerms());
}
}
}
return perms;
}
/**
* 通过用户id获取系统菜单
*
* @param userId 登录用户id
* @return {@link List}<{@link SysMenu}>
*/
private List<SysMenu> getSysMenusByUserId(Long userId){
List<SysMenu> sysMenus;
if (securityUtils.isAdmin(userId)) {
// 查所有目录和菜单
sysMenus = sysMenuService.queryMenusByUserId(null);
} else {
sysMenus = sysMenuService.queryMenusByUserId(userId);
}
// 转换成树结构
return sysMenus;
}
}
4 接口测试
返回的json
{
"code": 200,
"message": "加载登录用户信息成功!",
"data": {
"username": "admin",
"avatar": "https://img2.baidu.com/it/u=1437480680,2169625508&fm=253&fmt=auto&app=138&f=JPEG?w=360&h=360",
"sysMenus": [{
"id": 1,
"parentId": 0,
"label": "系统管理",
"path": "",
"perms": "sys:manage",
"type": 0,
"icon": "el-icon-setting",
"orderNum": 0,
"created": "2022-02-02 23:41:46",
"updated": "2022-02-02 23:41:48",
"children": [{
"id": 2,
"parentId": 1,
"label": "用户管理",
"path": "/sys/user",
"perms": "sys:user:list",
"type": 1,
"icon": "el-icon-user",
"orderNum": 0,
"created": "2022-02-02 23:43:34",
"updated": "2022-02-02 23:43:35",
"children": []
}, {
"id": 3,
"parentId": 1,
"label": "角色管理",
"path": "/sys/role",
"perms": "sys:role:list",
"type": 1,
"icon": "el-icon-user-solid",
"orderNum": 1,
"created": "2022-02-02 23:44:34",
"updated": "2022-02-02 23:44:36",
"children": []
}, {
"id": 4,
"parentId": 1,
"label": "菜单管理",
"path": "/sys/menu",
"perms": "sys:menu:list",
"type": 1,
"icon": "el-icon-menu",
"orderNum": 2,
"created": "2022-02-02 23:45:13",
"updated": "2022-02-02 23:45:15",
"children": []
}]
}, {
"id": 5,
"parentId": 0,
"label": "OA管理",
"path": "",
"perms": "oa:manage",
"type": 0,
"icon": "el-icon-thumb",
"orderNum": 1,
"created": "2022-02-05 03:21:08",
"updated": "2022-02-05 03:21:09",
"children": [{
"id": 6,
"parentId": 5,
"label": "群组管理",
"path": "/oa/group",
"perms": "oa:group:list",
"type": 1,
"icon": "el-icon-chat-round",
"orderNum": 0,
"created": "2022-02-05 03:22:42",
"updated": "2022-02-05 03:22:45",
"children": []
}, {
"id": 7,
"parentId": 5,
"label": "我的申请",
"path": "/oa/apply",
"perms": "oa:apply:list",
"type": 1,
"icon": "el-icon-stopwatch",
"orderNum": 1,
"created": "2022-02-05 03:23:33",
"updated": "2022-02-05 03:23:34",
"children": []
}, {
"id": 8,
"parentId": 5,
"label": "我的审批",
"path": "/oa/approve",
"perms": "oa:approve:list",
"type": 1,
"icon": "el-icon-key",
"orderNum": 2,
"created": "2022-02-05 03:24:42",
"updated": "2022-02-05 03:24:44",
"children": []
}]
}],
"perms": ["sys:manage", "oa:manage", "/sys/user", "sys:user:list", "/sys/role", "sys:role:list", "/sys/menu", "sys:menu:list", "/oa/group", "oa:group:list", "/oa/apply", "oa:apply:list", "/oa/approve", "oa:approve:list"]
}
}
5 路由权限拦截(此处只能拦截目录和菜单,拦截不了按钮)
在router/index.js中,加入elementui消息提示
import { Message } from 'element-ui';
加入路由拦截配置
登陆成功时,需要存储后台返回的token
localStorage.setItem('token')
首页加载时,需要存储后台返回的perms
localStorage.setItem('perms')
router.beforeEach((to, from, next) => {
if (to.path != '/' && to.path != '/login' && to.path != '/logout' && to.path != '/noPermission') {
// 检测是否登录
if (localStorage.getItem('token') == '') {
Message.error("用户未登录!");
next('/login');
} else {
// 1. index和home不需要鉴权
if (to.path == "/index" || to.path == "/home") {
next();
} else {
var perms = localStorage.getItem('perms')
if (perms == null) {
// 鉴权未通过
Message.error("鉴权未通过")
next("/noPermission")
} else {
// 鉴权通过
if (perms.indexOf(to.path) != -1) {
next()
} else {
// 鉴权未通过
Message.error("鉴权未通过")
next("/noPermission")
}
}
}
}
} else {
next()
}
})
编写鉴权401错误页面
<template>
<div class="noPermission">
<div class="errorContent">
<img
:src="errGif"
width="313px"
height="428px"
alt="Girl has dropped her ice cream."
/>
<h2 style="text-align: center">您没有访问权限!</h2>
</div>
</div>
</template>
<script>
import errGif from "@/assets/401.gif";
export default {
name: "NoPermission",
data() {
return {
errGif: errGif + "?" + +new Date(),
};
},
};
</script>
<style scoped>
.errorContent {
position: absolute;
left: 52%;
top: 48%;
transform: translate(-52%, -48%);
}
</style>
使用user用户,登录,直接通过url强制访问/sys/menu,路由守卫已经起作用了