• 权限管理系统-0.4.0


    五、权限管理

    5.1 引入JWT

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

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

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

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

            <dependency>
                <groupId>io.jsonwebtokengroupId>
                <artifactId>jjwtartifactId>
            dependency>
    
    • 1
    • 2
    • 3
    • 4

    创建工具类,用于生成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;
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    5.2 用户登录

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

    @ApiModel("登录信息类")
    @Data
    public class LoginVo {
    
        //用户名
        @ApiModelProperty("用户名")
        private String username;
    
        //用户密码
        @ApiModelProperty("密码")
        private String password;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    创建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"));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    修改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);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    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);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    //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;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    //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;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    
    <mapper namespace="pers.beiluo.yunshangoffice.mapper.SysMenuMapper">
    
        
        <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述

  • 相关阅读:
    pdf文档内容提取pdfplumber、PyPDF2
    ES分页查询方式脚本操作
    MATLAB - Gazebo 联合仿真 —— 使用 UR10 机械臂检测和采摘水果
    神经网络中的权重和偏置初始化
    2022.7.25-7.31 AI行业周刊(第108期):值钱比赚钱更重要
    JUC中的AQS底层详细超详解
    如何基于 GORM 实现 CreateOrUpdate 方法
    JavaScript学习总结(对象)
    Vim命令总结
    【软件工程之美 - 专栏笔记】34 | 账号密码泄露成灾,应该怎样预防?
  • 原文地址:https://blog.csdn.net/thdwx/article/details/136601446