若依框架----token权限控制逻辑

简介: 若依框架----token权限控制逻辑

在上一篇文章《开源框架若依中的权限控制逻辑-菜单》中,我们介绍了若依系统中的菜单管理的相关操作,最后遗留了一个小问题,为什么菜单的“路由参数”设置为非空时,菜单不会在左侧出现。今天我们就来深入的看看若依系统的菜单返回逻辑与后台数据设计。


接口捕获


我们打开若依系统,刷新页面,通过浏览器调试窗口看看调用了哪些网络请求:


在若依首页,我们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中的用户信息。

目录
相关文章
|
19天前
|
SQL XML Java
若依框架 --- 使用数据权限功能
若依框架 --- 使用数据权限功能
407 0
|
19天前
|
前端开发 数据安全/隐私保护
若依框架---权限控制角色设计
若依框架---权限控制角色设计
431 0
|
19天前
|
SQL
若依框架---角色与权限
若依框架---角色与权限
138 0
|
19天前
|
微服务
jeecg微服务项目调用接口报错Token验证失效的解决方法
jeecg微服务项目调用接口报错Token验证失效的解决方法
84 0
|
19天前
|
Java Spring
统一功能处理----拦截器
拦截器是Spring框架提供的核心功能之一,主要用来拦截用户的请求,在指定方法前后,根据业务需要执行预先设定的代码。拦截器就像小区门口的保安一样,当有人(外部请求)想要进入小区,保安就会先验证他的身份,身份正确才会放行;再你出小区后会做一些善后工作(如:关门……)。
45 2
|
19天前
|
缓存 前端开发 JavaScript
若依框架中的权限控制逻辑 ---- 菜单
若依框架中的权限控制逻辑 ---- 菜单
188 0
|
19天前
|
SQL 前端开发 数据安全/隐私保护
若依框架---权限管理设计
若依框架---权限管理设计
217 0
|
19天前
|
数据安全/隐私保护
若依框架---为什么把添加和更新分成两个接口
若依框架---为什么把添加和更新分成两个接口
60 0
|
10月前
|
安全
springsecurity配置类以及授权逻辑的编写
springsecurity配置类以及授权逻辑的编写
63 0
|
10月前
|
缓存 NoSQL 前端开发
若依系统(分离版)后台接口被调时,代码哪里判断了token是否超时?
若依系统(分离版)后台接口被调时,代码哪里判断了token是否超时?
523 0