权限管理系统-0.4.0

五、权限管理

5.1 引入JWT

JWT是JSON Web Token的缩写,即JSON Web令牌,是一种自包含令牌。 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。

JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。比如用在用户登录上。

JWT最重要的作用就是对 token信息的防伪作用。

在common-util模块中引入依赖:

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
        </dependency>

创建工具类,用于生成token和根据token获取用户名和用户id。

package pers.beiluo.yunshangoffice.common.jwt;

import io.jsonwebtoken.*;
import org.springframework.util.StringUtils;

import java.util.Date;

/**
 * 此类用于完成与token相关的功能
 * 例如:生成token或解析token等
 */
public class JWTHelper {

    //token失效时间
    private static long tokenExpiration = 365*24*60*60*1000;

    //签名,根据签名进行加密
    private static String tokenSignKey = "adcde";

    //创建token
    public static String createToken(Long userId,String username){
        return Jwts
                //创建JWT实例
                .builder()
                //设置类别,表示这个Jwt面向的用户
                .setSubject("AUTH-USER")
                //设置token的失效时间
                .setExpiration(new Date(System.currentTimeMillis()+tokenExpiration))
                //向claims属性中存值
                .claim("userId",userId)
                .claim("username",username)
                //使用signkey进行签名
                .signWith(SignatureAlgorithm.HS512,tokenSignKey)
                //设置压缩方法
                .compressWith(CompressionCodecs.GZIP)
                //返回完整的JWT
                .compact();
    }

    //获取用户id
    public static Long getUserId(String token){
        try {
            if(StringUtils.isEmpty(token)){
                return null;
            }
            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
            Claims body = claimsJws.getBody();
            //通过claim获取用户id
            return ((Integer)body.get("userId")).longValue();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //获取用户名称
    public static String getUsername(String token){
        try {
            if(StringUtils.isEmpty(token)){
                return null;
            }
            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
            Claims body = claimsJws.getBody();
            return (String)body.get("username");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}

5.2 用户登录

首先创建一个前后端数据交互的类:

@ApiModel("登录信息类")
@Data
public class LoginVo {

    //用户名
    @ApiModelProperty("用户名")
    private String username;

    //用户密码
    @ApiModelProperty("密码")
    private String password;

}

创建MD5密码加密工具类:

package pers.beiluo.yunshangoffice.common.jwt;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


public final class MD5 {

    public static String encrypt(String strSrc) {
        try {
            char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
                    '9', 'a', 'b', 'c', 'd', 'e', 'f' };
            byte[] bytes = strSrc.getBytes();
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(bytes);
            bytes = md.digest();
            int j = bytes.length;
            char[] chars = new char[j * 2];
            int k = 0;
            for (int i = 0; i < bytes.length; i++) {
                byte b = bytes[i];
                chars[k++] = hexChars[b >>> 4 & 0xf];
                chars[k++] = hexChars[b & 0xf];
            }
            return new String(chars);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException("MD5加密出错!!+" + e);
        }
    }

    public static void main(String[] args) {
        System.out.println(MD5.encrypt("111111"));
    }
}

修改IndexController中的方法:

    @ApiOperation("登录")
    @PostMapping("/login")
    public Result login(@RequestBody LoginVo loginVo){
        //根据用户名查询数据库
        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysUserLambdaQueryWrapper.eq(SysUser::getUsername,loginVo.getUsername());
        SysUser one = sysUserService.getOne(sysUserLambdaQueryWrapper);
        //判断该用户是否存在
        if(null == one){
            throw new CustomizedException(201,"用户尚未注册");
        }
        //判断密码是否正确
        if(!one.getPassword().equals(MD5.encrypt(loginVo.getPassword()))){
            throw new CustomizedException(201,"用户名或密码错误");
        }
        //判断用户是否有效
        if(one.getStatus().intValue() == 0){
            throw new CustomizedException(201,"用户已被禁用");
        }
        //走到这里说明用户验证成功,返回token
        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        stringObjectHashMap.put("token", JWTHelper.createToken(one.getId(),one.getUsername()));
        return Result.ok(stringObjectHashMap);
    }

5.3 返回用户信息

//IndexController
    @ApiOperation("获取用户信息")
    @GetMapping("/info")
    public Result getInfo(HttpServletRequest request){
        //首先获取token
        String token = request.getHeader("token");
        //根据token获取用户id
        Long userId = 1L;//JWTHelper.getUserId(token);
        //获取用户信息
        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysUserLambdaQueryWrapper.eq(SysUser::getId,userId);
        SysUser one = sysUserService.getOne(sysUserLambdaQueryWrapper);
        //获取用户角色信息
        Map<String, Object> roleOfUserById = sysUserService.getRoleOfUserById(userId);
        ArrayList<SysRole> assignedRole = (ArrayList<SysRole>) roleOfUserById.get("assignedRole");
        List<String> collect = assignedRole.stream().map(item -> item.getRoleName()).collect(Collectors.toList());
        //根据用户id获取菜单信息
        List<RouterVo> menuList = sysMenuService.getUserRouterList(userId);
        //根据用户id获取按钮权限信息
        List<String> permissionList = sysMenuService.getUserPermissionList(userId);
        //创建返回对象
        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        stringObjectHashMap.put("name",one.getName());
        stringObjectHashMap.put("avatar","https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        stringObjectHashMap.put("roles",collect);
        stringObjectHashMap.put("buttons",permissionList);
        stringObjectHashMap.put("routers",menuList);
        return Result.ok(stringObjectHashMap);
    }
//SysMenuServiceImpl.getUserRouterList
    /**
     * 根据用户id获取菜单的路由结构
     * @param userId
     * @return
     */
    @Override
    public List<RouterVo> getUserRouterList(Long userId) {
        List<SysMenu> sysMenus = null;
        //判断是否为管理员,如果为管理员则直接返回所有菜单,假设用户id为1的是管理员,其余都为普通用户
        if(userId.longValue() == 1){
            LambdaQueryWrapper<SysMenu> sysMenuLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysMenuLambdaQueryWrapper.eq(SysMenu::getStatus,1);
            //按照sort_value进行排序
            sysMenuLambdaQueryWrapper.orderByAsc(SysMenu::getSortValue);
            sysMenus = baseMapper.selectList(sysMenuLambdaQueryWrapper);
        }else{
            sysMenus = baseMapper.selectUserMenuList(userId);
        }
        //将用户拥有菜单转换成树形
        List<SysMenu> sysMenus1 = MyUtils.buildMenu(sysMenus);
        //创建返回对象,将树形菜单转换成路由形式
        ArrayList<RouterVo> routerVos = MyUtils.buildRouter(sysMenus1);
        return routerVos;
    }
//SysMenuServiceImpl
    /**
     * 根据用户id查询用户拥有的按钮权限
     * @param userId
     * @return
     */
    @Override
    public List<String> getUserPermissionList(Long userId) {
        List<SysMenu> sysMenus = new ArrayList<>();
        //如果用户为管理员,则查询所有菜单
        if(userId.longValue() == 1){
            LambdaQueryWrapper<SysMenu> sysMenuLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysMenuLambdaQueryWrapper.eq(SysMenu::getStatus,1);
            sysMenus = baseMapper.selectList(sysMenuLambdaQueryWrapper);
        }else{
            sysMenus = baseMapper.selectUserMenuList(userId);
        }
        //从菜单列表中获取可以操作的按钮权限
        List<String> collect = sysMenus.stream()
                .filter(ele -> ele.getType() == 2)
                .map(ele -> ele.getPerms())
                .collect(Collectors.toList());
        return collect;
    }
<!--SysMenuMapper.selectUserMenuList,这个方法涉及多表联查,所以需要在xml文件中定义-->
<mapper namespace="pers.beiluo.yunshangoffice.mapper.SysMenuMapper">

    <!--映射关系
        在实体类中可以使用@TableField注解指定表字段与类字段的映射关系,在这里就可以开启自动映射
        如果开启了驼峰命名,并且是按照规范命名的,那么就不需要使用@TableFiled注解,也不需要resultMap标签-->
    <resultMap id="userMenuMap" type="pers.beiluo.yunshangoffice.model.system.SysMenu" autoMapping="true">

    </resultMap>

    <!--抽取列名-->
    <sql id="columns">
        sm.id,sm.parent_id,sm.name,sm.type,sm.path,sm.component,sm.perms,sm.icon,sm.sort_value,sm.status,sm.create_time,sm.update_time,sm.is_deleted
    </sql>
    
    <select id="selectUserMenuList" resultMap="userMenuMap">
        SELECT DISTINCT <include refid="columns" />
        FROM sys_role_menu srm INNER JOIN
        sys_menu sm ON srm.menu_id=sm.id
        INNER JOIN sys_user_role sur ON
        srm.role_id=sur.role_id
        WHERE sur.user_id=#{userId}
        AND sm.status=1
        AND srm.is_deleted=0
        AND sm.is_deleted=0
        AND srm.is_deleted=0
    </select>

</mapper>

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/448870.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32CubeIDE基础学习-STM32CubeIDE软件新增工程文件夹

STM32CubeIDE基础学习-STM32CubeIDE软件新增工程文件夹 文章目录 STM32CubeIDE基础学习-STM32CubeIDE软件新增工程文件夹前言第1章 添加文件夹第2章 添加文件路径2.1 相对路径方法2.2 绝对路径方法 总结 前言 在编程的过程中&#xff0c;如果需要在原有的工程基础上新增其它的…

C 嵌入式系统设计模式 24:安全性和可靠性介绍

本书的原著为&#xff1a;《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》&#xff0c;讲解的是嵌入式系统设计模式&#xff0c;是一本不可多得的好书。 本系列描述我对书中内容的理解。本文章描述嵌入式安全性和可靠性模式之一…

二叉搜索树题目:前序遍历构造二叉搜索树

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 解法三思路和算法代码复杂度分析 解法四思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;前序遍历构造二叉搜索树 出处&#xff1a;1008. …

Anacond 安装及使用教程pytorch安装

下载网址&#xff1a;Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror pycharm安装教程 【从Python基础到深度学习】1. Python PyCharm安装及激活-CSDN博客 pycharm添加anaconda环境 conda创建虚拟环境 base表示当前conda的base环境&a…

sheng的学习笔记- AI-类别不平衡问题

目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 什么是类别不平衡问题 类别不平衡&#xff08;class-imbalance&#xff09;&#xff0c;也叫数据倾斜&#xff0c;数据不平衡&#xff0c;就是指分类任务中不同类别的训练样例数目差别很大的情况。 例如有998个反例&#xf…

【智能算法】蜻蜓算法(DA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.代码实现4.参考文献 1.背景 2016年&#xff0c;Mirjalili受到蜻蜓静态和动态集群行为启发&#xff0c;提出了蜻蜓算法(Dragonfly algorithm, DA)。 2.算法原理 2.1算法思想 蜻蜓集群有两种行为目的&#xff1a;狩猎&#xf…

大模型相关整理

机器学习 模型就是函数&#xff0c;这个函数可能是一个很简单的线性函数&#xff0c;也可以是一个非常复杂的高阶函数、或者是一个多层的神经网络函数。 机器学习领域的很多研究和方法都是在尝试设计这个函数&#xff0c;以自动驾驶领域为例&#xff0c;之前的自动驾驶基于人…

四川宏博蓬达法律咨询有限公司:专业可靠,您身边的法律守护者

在现代社会&#xff0c;法律咨询服务的需求日益增长&#xff0c;选择一家专业可靠的法律咨询公司成为了许多企业和个人的当务之急。四川宏博蓬达法律咨询有限公司便是这样一个值得信赖的法律服务提供者&#xff0c;以其专业、高效、贴心的服务&#xff0c;赢得了广大客户的信赖…

c++ primer plus笔记 第十八章 探讨c++新标准

复习前面的内容&#xff1a; 1.auto&#xff0c;可以自动识别auto本身在这种语境下是什么类型 2.decltype,让一个变量的类型和另外一个变量的类型相同 decltype(x) y;//让y的类型和x的类型相同 如何理解&#xff1f; decltype是一个关键词&#xff0c;其作用是检查括号内的…

【MySQL系列 05】Schema 与数据类型优化

良好的数据库 schema 设计和合理的数据类型选择是 SQL 获得高性能的基石。 一、选择优化的数据类型 MySQL 支持的数据类型非常多&#xff0c;选择正确的数据类型对于获得高性能至关重要。不管存储哪种类型的数据&#xff0c;下面几个简单的原则都有助于做出更好的选择。 1. …

AOP-注解实现-记录日志到数据库

概念解释 AOP&#xff1a;Aspect Oriented Programming Aspect&#xff1a;方面Oriented&#xff1a;面向…的Programming编程 之前我对模块化编程的认识&#xff0c;主要是局限在布局结构、目录结构上。比如Vue的template模板。 对方法的模块化编程&#xff0c;我之前的认识…

基于springboot+layui仓库管理系统设计和实现

基于 java springbootlayui仓库管理系统设计和实现 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获取…

硬件工程师面试题梳理-百度硬件面试题

硬件工程师基本职责 在公司里面&#xff0c;硬件工程师的主要职责包括设计、开发和测试硬件系统&#xff0c;以满足产品需求和性能要求。他们负责确保硬件系统的可靠性、稳定性和可维护性&#xff0c;并与软件工程师和其他团队成员合作&#xff0c;以确保硬件和软件的协同工作…

arcgis辅助下的GIS滑坡泥石流易发性评估模型构建

我国是地质灾害多发国家&#xff0c;地质灾害的发生无论是对于地质环境还是人类生命财产的安全都会带来较大的威胁&#xff0c;因此需要开展地质灾害风险普查。利用遥感&#xff08;RS&#xff09;技术进行地质灾害调查工作具有宏观、快速、准确的特点&#xff0c;能反映出地质…

SpringCloud(21)之SpringCloud Alibaba Nacos实战应用

一、Nacos安装 1.1 Nacos概述 Nacos是Alibaba微服务生态组件中的重要组件之一&#xff0c;主要用它实现应用的动态服务发现、配置管理、 服务管理。Nacos discovery alibaba/spring-cloud-alibaba Wiki GitHub Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简…

MotionCtrl: A Unified and Flexible Motion Controller for Video Generation

MotionCtrl: A Unified and Flexible Motion Controller for Video Generation 这篇论文是基于VideoCrafter的&#xff0c;而VideoCrafter是基于LVDM的 关于LVDM可以看https://blog.csdn.net/Are_you_ready/article/details/136615853 2023年12月6日发表在arxiv 这篇论文讨论…

seo js转码工具

js转码工具作用 用于把js加密 如果不想让别人看到自己的js 代码就可以使用这个方法 js工具网址 https://tool.chinaz.com/js.aspx 效果

J.K.罗琳创作的《神奇动物》系列电影赏析

故事情节 《神奇动物在哪里》&#xff1a; 这部电影讲述了纽特斯卡曼德来到纽约的故事&#xff0c;他是一位收集和研究魔法动物的巫师。在纽约&#xff0c;他的一只神奇生物逃脱&#xff0c;并引发了一系列麻烦。与此同时&#xff0c;纽约巫师社会面临着黑暗力量的威胁&#x…

超大规模-近场

这里先了解基站到用户的&#xff0c;无RIS的近场模型 超大规模智能反射面辅助的近场移动通信研究 &#xff08;论文题目&#xff09; &#xff08;期刊&#xff09;无线电通信技术 系统&#xff1a;BS-RIS-UE&#xff0c;两个阶段都是近场 模型&#xff1a;球面波传播模型&…

在dpvs上实现ICMP的源进源出

目录 1. 缘起2. 源码分析3. 让ICMP也走源进源出1. 缘起 在网络通信中,当一个请求报文从源主机到达目标主机,并经过中间路由器或交换机进行转发时,请求报文进入主机A的路径和响应报文离开主机A的路径可能不同。这种情况下,就会出现所谓的三角路径问题。如下图: 具体来说,…