写在最前
如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。
源码地址(后端):gitee.com/csps/mingyu…
源码地址(前端):gitee.com/csps/mingyu…
文档地址:gitee.com/csps/mingyu…
前情回顾
之前我们设计了权限模型并提交了数据库脚本,然后通过 mingyue-common-gen
模块 MingYueCommonGenDemo
生成了基础代码,接下来我们需要提供两个关键接口:
TIPS
为了严格按照 RESTful 接口风格设计,变更现有接口命名: getSysUserInfoByUsername => userInfo
、getSysUsers => list
,后续接口也将严格按照 RESTful 接口风格设计。
登录缓存用户信息
Session 会话
Session 是会话中专业的数据缓存组件,通过 Session 我们可以很方便的缓存一些高频读写数据,提高程序性能,例如:
// 在登录时缓存 user 对象
StpUtil.getSession().set("user", user);
// 然后我们就可以在任意处使用这个 user 对象
SysUser user = (SysUser) StpUtil.getSession().get("user");
在 Sa-Token 中,Session 分为三种,分别是:
Account-Session
: 指的是框架为每个账号 id 分配的 SessionToken-Session
: 指的是框架为每个 token 分配的 SessionCustom-Session
: 指的是以一个特定的值作为 SessionId,来分配的 Session
Token-Session
缓存用户信息
public static void login(SysUser userInfo) {
// 请求作用域:存储的数据只在一次请求内有效,请求结束后数据自动清除。
SaStorage storage = SaHolder.getStorage();
storage.set(LOGIN_USER_KEY, userInfo);
storage.set(USER_KEY, userInfo.getUserId());
// 第1步,先登录上
StpUtil.login(userInfo.getUserId());
// 第3步,缓存用户信息
StpUtil.getTokenSession().set(LOGIN_USER_KEY, userInfo);
}
获取用户信息
public static SysUser getLoginUser() {
SysUser loginUser = (SysUser) SaHolder.getStorage().get(LOGIN_USER_KEY);
if (loginUser != null) {
return loginUser;
}
loginUser = (SysUser) StpUtil.getTokenSession().get(LOGIN_USER_KEY);
SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
return loginUser;
}
接口测试
@GetMapping("info")
@Operation(summary = "获取当前用户全部信息")
public R userInfo() {
SysUser sysUser = LoginHelper.getLoginUser();
System.out.println("=============================");
System.out.println(JSONUtil.toJsonStr(sysUser));
System.out.println("=============================");
return R.ok(null);
}
接口调用打印如下:
=============================
{"userId":1,"username":"mingyue","nickname":"明月","sex":"0","password":"123456","phone":"13288888888","status":"0","isDeleted":"0","createTime":1689757582000,"updateTime":1689757585000,"createBy":"mingyue","updateBy":"mingyue"}
=============================
获取用户权限信息
接口层
@GetMapping("info")
@Operation(summary = "获取当前登录用户全部信息")
public R userInfo() {
return R.ok(sysUserService.getUserInfo());
}
业务层
@Override
public UserInfoVo getUserInfo() {
UserInfoVo result = new UserInfoVo();
SysUser sysUser = LoginHelper.getLoginUser();
// 密码置空
sysUser.setPassword(null);
result.setSysUser(sysUser);
// 设置角色列表
Set rolePermission = sysRoleService.getRolePermission(sysUser.getUserId());
result.setRoles(rolePermission);
// 设置权限列表
Set menuPermission = sysMenuService.getMenuPermission(sysUser.getUserId());
result.setRoles(menuPermission);
return result;
}
测试接口
Authorization Token 通过登录接口获取
curl -X 'GET' \
'http://mingyue-gateway:9100/system/sysUser/info' \
-H 'accept: */*' \
-H 'Authorization: vXPJnADIcTPfKuP3reBYmmUAi4xjw8nf'
接口返回
{
"code": 200,
"msg": "操作成功",
"data": {
"sysUser": {
"userId": 1,
"username": "mingyue",
"nickname": "明月",
"sex": "0",
"password": null,
"phone": "13288888888",
"email": null,
"avatar": null,
"status": "0",
"isDeleted": "0",
"createTime": "2023-07-19T17:06:22",
"updateTime": "2023-07-19T17:06:25",
"createBy": "mingyue",
"updateBy": "mingyue"
},
"permissions": null,
"roles": [
null,
"system:user:list"
]
}
}
获取用户路由信息
接口层
@GetMapping("getRouters")
@Operation(summary = "获取路由信息")
public R getRouters() {
Long userId = LoginHelper.getLoginUser().getUserId();
return R.ok(sysMenuService.getRouters(userId));
}
业务层
@Override
public List getRouters(Long userId) {
List sysMenus = sysMenuMapper.selectMenuTreeByUserId(userId);
return this.recursionMenu(sysMenus, -1L);
}
/**
* 递归菜单,构建菜单树
*/
private List recursionMenu(List sysMenus, Long pid) {
List tree = CollUtil.newArrayList();
for (SysMenu menu : sysMenus) {
if (menu.getParentId().equals(pid)) {
RouterVo router = new RouterVo();
router.setPath("/" + menu.getPath());
router.setName(menu.getPath());
router.setComponent(menu.getComponent());
router.setRedirect(menu.getRedirect());
MetaVo metaVo = new MetaVo();
metaVo.setTitle(menu.getMenuName());
metaVo.setIsLink(menu.getIsLink());
metaVo.setIsHide(UserConstants.IS_HIDE.equals(menu.getIsHide()));
metaVo.setIsKeepAlive(UserConstants.IS_KEEP_ALIVE.equals(menu.getIsKeepAlive()));
metaVo.setIsAffix(UserConstants.IS_AFFIX.equals(menu.getIsAffix()));
metaVo.setIsIframe(UserConstants.IS_IFRAME.equals(menu.getIsIframe()));
metaVo.setIcon(menu.getIcon());
router.setMeta(metaVo);
router.setChildren(recursionMenu(sysMenus, menu.getMenuId()));
tree.add(router);
}
}
return tree;
}
测试接口
curl -X 'GET' \
'http://mingyue-gateway:9100/system/sysMenu/getRouters' \
-H 'accept: */*'
-H 'Authorization: vXPJnADIcTPfKuP3reBYmmUAi4xjw8nf'
接口返回
{
"code": 200,
"msg": "操作成功",
"data": [
{
"path": "/system",
"name": "system",
"component": null,
"redirect": null,
"meta": {
"title": "系统管理",
"isLink": "0",
"isHide": false,
"isKeepAlive": false,
"isAffix": false,
"isIframe": false,
"icon": "iconfont icon-xitongshezhi"
},
"children": [
{
"path": "/user",
"name": "user",
"component": "/system/user",
"redirect": null,
"meta": {
"title": "用户管理",
"isLink": "0",
"isHide": false,
"isKeepAlive": false,
"isAffix": false,
"isIframe": false,
"icon": "iconfont icon-icon-"
},
"children": []
},
...
]
}
]
}
小结
现在用户已经拿到权限点了,接下来整合一下权限点与 Sa-Token 的使用,看看 Sa-Token 如何通过权限点控制接口访问。