• 搭建gataway鉴权流程


    先完善Login接口

    controller

    
    @RestController
    @RequestMapping("/login")
    @Api(value = "管理API",tags = "用户登录")
    @CrossOrigin
    public class LoginController {
    
        @Autowired
        private IAdUserService adUserService;
    
        @PostMapping("/in")
        @ApiOperation(value = "用户登录" ,notes = "用户登录")
        @ApiModelProperty(name ="dto" ,dataType = "LoginDto" ,required = true)
        public ResponseResult login(@RequestBody LoginDto dto){
            return adUserService.login(dto);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    service

        @Override
        public ResponseResult login(LoginDto dto) {
    //        先做判断:用户名和密码都不能为空
    
            if( StringUtils.isBlank(dto.getName())||StringUtils.isBlank(dto.getPassword()) ) {
               return ResponseResult.errorResult(AppHttpCodeEnum.NAME_PASSWORD_NOTNULL) ;
            }
            LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    //        先根据用户名查询
            queryWrapper.eq(AdUser::getName,dto.getName());
            AdUser one = this.getOne(queryWrapper);
            if(one==null){
                return ResponseResult.errorResult(AppHttpCodeEnum.USER_NOT_EXIST) ;
            }
    //                如果查询到用户后再比较密码
            String password = one.getPassword();// c从表中获取的 是密文的
            String password1 = dto.getPassword();//从页面来的 是明文的
    //        把明文转成密文
            password1 = DigestUtils.md5Hex(password1+one.getSalt());
    
            if (!StringUtils.equals(password,password1)) {
                return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR) ;
            }
    
    //        ================
    
            Map resultMap = new HashMap();
            one.setPassword("");
            one.setSalt("");
            one.setPhone("");
            resultMap.put("user",one);
    
            Map claimMaps = new HashMap<>();
            claimMaps.put("userId",one.getId());
            claimMaps.put("name",one.getName());
            String token = AppJwtUtil.getToken(claimMaps);
            resultMap.put("token",token);
    
            return ResponseResult.okResult(resultMap);
        }
    
    • 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

    gataway的配置

    说到底我们这里还是使用Filter进行配置,先整理一下思路再去选用工具类

    1. 用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进行登录
    2. 用户登录成功,后台管理微服务签发JWT TOKEN信息返回给用户
    3. 用户再次进入网关开始访问,网关过滤器接收用户携带的TOKEN
    4. 网关过滤器解析TOKEN ,判断是否有权限,如果有,则放行,如果没有则返回未认证错误
    @Component
    public class AuthFilter implements GlobalFilter, Ordered {
    
        @Override
        public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            ServerHttpResponse response = exchange.getResponse();
            ServerHttpRequest request = exchange.getRequest();
    //        判断是否为登录操作  如果是登录操作直接放行
            String path = request.getURI().getPath();  // api/v1/channel/list  /login/in
            if(path.contains("/login")){
                return chain.filter(exchange);  //直接放行
            }
    
            String token = request.getHeaders().getFirst("token");
     //        判断请求头中是否携带token 如果没有直接返回401
            if(StringUtils.isBlank(token)){
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
    //        如果携带token判断token是否有效
            Claims claims = AppJwtUtil.getClaimsBody(token);
            if(claims!=null){
                //        如果有效从token中解析出userId和name放到请求头中继续进入到后面的微服务中
                int type = AppJwtUtil.verifyToken(claims);
    //            -1:有效,0:有效
                if(type==-1||type==0){
                    Integer userId = claims.get("userId", Integer.class);
                    String name = claims.get("name", String.class);
                    request.mutate().header("userId",userId.toString());
                    request.mutate().header("name",name);
                    return chain.filter(exchange);  //放行
                }
            }
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
    
        @Override
        public int getOrder() {
            return 0;
    
        }
    }
    
    • 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

    工具类 JwtUtil

    public class AppJwtUtil {
    
        // TOKEN的有效期一天(MS)
    //    private static final int TOKEN_TIME_OUT = 3600 * 1000 * 24;
        private static final int TOKEN_TIME_OUT = 60 * 1000 ;
        // 加密KEY
        private static final String TOKEN_ENCRY_KEY = "MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY";
        // 最小刷新间隔(S)
        private static final int REFRESH_TIME = 300;
    
        /**
         * 生成token
         *
         * @param claimMaps 自定义信息
         * @return
         */
        public static String getToken(Map claimMaps) {
            long currentTime = System.currentTimeMillis();
            return Jwts.builder()
                    .setId(UUID.randomUUID().toString())
                    .setIssuedAt(new Date(currentTime))  //签发时间
                    .setSubject("system")  //说明
                    .setIssuer("vhr") //签发者信息
                    .setAudience("app")  //接收用户
                    .compressWith(CompressionCodecs.GZIP)  //数据压缩方式
                    .signWith(SignatureAlgorithm.HS512, generalKey()) //加密方式
                    .setExpiration(new Date(currentTime + TOKEN_TIME_OUT))  //过期时间戳
                    .addClaims(claimMaps) //cla信息
                    .compact();
        }
    
        /**
         * 获取token中的claims信息
         *
         * @param token
         * @return
         */
        private static Jws getJws(String token) {
            return Jwts.parser()
                    .setSigningKey(generalKey())
                    .parseClaimsJws(token);
        }
    
        /**
         * 获取payload body信息
         *
         * @param token
         * @return
         */
        public static Claims getClaimsBody(String token) {
            try {
                return getJws(token).getBody();
            } catch (ExpiredJwtException e) {
                return null;
            }
        }
    
        /**
         * 获取hearder body信息
         *
         * @param token
         * @return
         */
        public static JwsHeader getHeaderBody(String token) {
            return getJws(token).getHeader();
        }
    
        /**
         * 是否过期
         *
         * @param claims
         * @return -1:有效,0:有效,1:过期,2:过期
         */
        public static int verifyToken(Claims claims) {
            if (claims == null) {
                return 1;
            }
            try {
                claims.getExpiration()
                        .before(new Date());
                if ((claims.getExpiration().getTime() - System.currentTimeMillis()) > REFRESH_TIME * 1000) {
                    return -1;
                } else {
                    return 0;
                }
            } catch (ExpiredJwtException ex) {
                return 1;
            } catch (Exception e) {
                return 2;
            }
        }
    
        /**
         * 由字符串生成加密key
         *
         * @return
         */
        public static SecretKey generalKey() {
            byte[] encodedKey = Base64.getEncoder().encode(TOKEN_ENCRY_KEY.getBytes());
            SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
            return key;
        }
    
        public static void main(String[] args) {
    //        Map map = new HashMap();
    //        map.put("userId", "10001");
    //        map.put("userName", "tom");
    //        String token = AppJwtUtil.getToken(map);
    //        System.out.println(token);
    
            String token ="NEdtwKL_ipswZnXIJoR3nQvdlAjI1GTrclTvV3szj2-R9XSEQsQ-lpS9JQQ00G6BdH2PDfFxmDT17xDj8XEzZll0LUvcFFROX5I_eA";
    
            Jws jws = AppJwtUtil.getJws(token);
            Claims claims = jws.getBody();
            System.out.println(claims.get("userId"));
            System.out.println(claims.get("userName"));
        }
    
    }
    
    • 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
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
  • 相关阅读:
    63. 不同路径 II java解决
    如何加快香山处理器Chisel->Verilog编译速度
    你所不知道的端口耗尽(一)
    java知识点快速过
    Android studio 实现生成二维码和扫描二维码
    电容笔和Apple Pencil的区别是什么?双十一值得入手的电容笔
    SSM 框架整合
    基于C#和OpenVINO在英特尔独立显卡上部署PP-TinyPose模型
    Linux 学习笔记 2022-11-12---------Linux基础
    Multi Scale Supervised 3D U-Net for Kidney and Tumor Segmentation
  • 原文地址:https://blog.csdn.net/weixin_43189971/article/details/128136417