018从零搭建微服务系统服务(五)

2023年 8月 9日 64.5k 0

写在最前

如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。

源码地址(后端):gitee.com/csps/mingyu…

源码地址(前端):gitee.com/csps/mingyu…

文档地址:gitee.com/csps/mingyu…

前情回顾

之前我们设计了权限模型并提交了数据库脚本,然后通过 mingyue-common-gen 模块 MingYueCommonGenDemo 生成了基础代码,接下来我们需要提供两个关键接口:

  • 获取用户权限信息;
  • 获取用户路由信息;
  • TIPS

    为了严格按照 RESTful 接口风格设计,变更现有接口命名: getSysUserInfoByUsername => userInfogetSysUsers => 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 分配的 Session
    • Token-Session: 指的是框架为每个 token 分配的 Session
    • Custom-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 如何通过权限点控制接口访问。

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论