开源框架若依中的权限控制逻辑-token转换为用户信息的后端接口
【摘要】 从菜单的前端到后端在上一篇文章《开源框架若依中的权限控制逻辑-菜单》中,我们介绍了若依系统中的菜单管理的相关操作,最后遗留了一个小问题,为什么菜单的“路由参数”设置为非空时,菜单不会在左侧出现。今天我们就来深入的看看若依系统的菜单返回逻辑与后台数据设计。 接口捕获我们打开若依系统,刷新页面,通过浏览器调试窗口看看调用了哪些网络请求:在若依首页,我们F12打开浏览器调试窗口,并切换到“网络”...
从菜单的前端到后端
在上一篇文章《开源框架若依中的权限控制逻辑-菜单》中,我们介绍了若依系统中的菜单管理的相关操作,最后遗留了一个小问题,为什么菜单的“路由参数”设置为非空时,菜单不会在左侧出现。今天我们就来深入的看看若依系统的菜单返回逻辑与后台数据设计。
接口捕获
我们打开若依系统,刷新页面,通过浏览器调试窗口看看调用了哪些网络请求:
在若依首页,我们F12打开浏览器调试窗口,并切换到“网络”页面,勾选过滤条件“Fetch/XHR”,然后刷新页面。捕获的请求如下图所示:
我们依次查看各个请求分别获取了什么信息。
getInfo
getInfo的全部请求信息如下:
请求网址: http://localhost/dev-api/getInfo, 请求方法: GET。
请求标头包括Authorization,Cookie等信息。
返回信息如下:
{
"msg": "操作成功",
"code": 200,
"permissions": [
"*:*:*"
],
"roles": [
"admin"
],
"user": {
"searchValue": null,
"createBy": "admin",
"createTime": "2021-10-12 08:45:24",
"updateBy": null,
"updateTime": null,
"remark": "管理员",
"params": {},
"userId": 1,
"deptId": 103,
"userName": "admin",
"nickName": "若依",
"email": "ry@163.com",
"phonenumber": "15888888888",
"sex": "1",
"avatar": "",
"salt": null,
"status": "0",
"delFlag": "0",
"loginIp": "127.0.0.1",
"loginDate": "2022-04-03T17:06:44.000+08:00",
"dept": {
"searchValue": null,
"createBy": null,
"createTime": null,
"updateBy": null,
"updateTime": null,
"remark": null,
"params": {},
"deptId": 103,
"parentId": 101,
"ancestors": null,
"deptName": "研发部门",
"orderNum": "1",
"leader": "若依",
"phone": null,
"email": null,
"status": "0",
"delFlag": null,
"parentName": null,
"children": []
},
"roles": [
{
"searchValue": null,
"createBy": null,
"createTime": null,
"updateBy": null,
"updateTime": null,
"remark": null,
"params": {},
"roleId": 1,
"roleName": "超级管理员",
"roleKey": "admin",
"roleSort": "1",
"dataScope": "1",
"menuCheckStrictly": false,
"deptCheckStrictly": false,
"status": "0",
"delFlag": null,
"flag": false,
"menuIds": null,
"deptIds": null,
"admin": true
}
],
"roleIds": null,
"postIds": null,
"roleId": null,
"admin": true
}
}
其返回信息主要包括:权限permissions, 角色roles,当前登录用户信息user,user中又包括当前用户的基础信息,部门信息,角色信息等。
我们后台来查看其接口执行逻辑。
/**
* 获取用户信息
*
* @return 用户信息
*/
@GetMapping("getInfo")
public AjaxResult getInfo()
{
SysUser user = SecurityUtils.getLoginUser().getUser();
// 角色集合
Set<String> roles = permissionService.getRolePermission(user);
// 权限集合
Set<String> permissions = permissionService.getMenuPermission(user);
AjaxResult ajax = AjaxResult.success();
ajax.put("user", user);
ajax.put("roles", roles);
ajax.put("permissions", permissions);
return ajax;
}
首先,通过Spring-Security来根据登录token信息获取用户信息,即:
SysUser user = SecurityUtils.getLoginUser().getUser();
我们依次深入方法,其调用链条:
SecurityContextHolder.getContext().getAuthentication().getLoginUser()
其设置位置位于过滤器中:
package com.ruoyi.framework.security.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
/**
* token过滤器 验证token有效性
*
* @author ruoyi
*/
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
{
@Autowired
private TokenService tokenService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException
{
LoginUser loginUser = tokenService.getLoginUser(request);
if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
{
tokenService.verifyToken(loginUser);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
chain.doFilter(request, response);
}
}
在token转换为用户信息的关键代码是:
LoginUser loginUser = tokenService.getLoginUser(request);
其方法体为:
/**
* 获取用户身份信息
*
* @return 用户信息
*/
public LoginUser getLoginUser(HttpServletRequest request)
{
// 获取请求携带的令牌
String token = getToken(request);
if (StringUtils.isNotEmpty(token))
{
try
{
Claims claims = parseToken(token);
// 解析对应的权限以及用户信息
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid);
LoginUser user = redisCache.getCacheObject(userKey);
return user;
}
catch (Exception e)
{
}
}
return null;
}
如此,便通过将token转换为了保存在redis中的用户信息。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)