当前位置: 首页 > news >正文

搭建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);
    }
}

service

    @Override
    public ResponseResult login(LoginDto dto) {
//        先做判断:用户名和密码都不能为空

        if( StringUtils.isBlank(dto.getName())||StringUtils.isBlank(dto.getPassword()) ) {
           return ResponseResult.errorResult(AppHttpCodeEnum.NAME_PASSWORD_NOTNULL) ;
        }
        LambdaQueryWrapper<AdUser> 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<String, Object> 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);
    }

gataway的配置

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

  1. 用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进行登录
  2. 用户登录成功,后台管理微服务签发JWT TOKEN信息返回给用户
  3. 用户再次进入网关开始访问,网关过滤器接收用户携带的TOKEN
  4. 网关过滤器解析TOKEN ,判断是否有权限,如果有,则放行,如果没有则返回未认证错误
@Component
public class AuthFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> 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;

    }
}

工具类 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<String, Object> 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<Claims> 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<Claims> jws = AppJwtUtil.getJws(token);
        Claims claims = jws.getBody();
        System.out.println(claims.get("userId"));
        System.out.println(claims.get("userName"));
    }

}

相关文章:

  • Codeforces Round #835 (Div. 4)A.B.C.D.E.F
  • flask入门教程之数据库保存
  • 网站变灰白css
  • Template类创建模板替换字符串
  • MySQL日志(undo log 和 redo log 实现事务的原子性/持久性/一致性)
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • 培养出最多亿万富翁的美国大学TOP10榜单
  • 蓝桥杯嵌入式AD采样解析
  • 数据结构和算法——基于Java——4.1栈(数组实现栈、链表实现栈)
  • 怎么看网站域名有没有收录 收录情况怎么样 网站收录查询
  • 信号发生器不会用?一篇文章教会你
  • Java+JSP+MySQL基于SSM的医院挂号就诊系统-计算机毕业设计
  • 今年十八,喜欢ctf-web
  • AI加速(九): 深度理解吞吐量和延时
  • java毕业设计的滑雪场学具租赁管理系统mybatis+源码+调试部署+系统+数据库+lw
  • 分享一款快速APP功能测试工具
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • QQ浏览器x5内核的兼容性问题
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • 前端路由实现-history
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 使用putty远程连接linux
  • 问题之ssh中Host key verification failed的解决
  • 我的zsh配置, 2019最新方案
  • 想使用 MongoDB ,你应该了解这8个方面!
  •  一套莫尔斯电报听写、翻译系统
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • 浅谈sql中的in与not in,exists与not exists的区别
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • #FPGA(基础知识)
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (2)(2.10) LTM telemetry
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (分布式缓存)Redis持久化
  • (附源码)springboot宠物管理系统 毕业设计 121654
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (转)IOS中获取各种文件的目录路径的方法
  • .【机器学习】隐马尔可夫模型(Hidden Markov Model,HMM)
  • .aanva
  • .NET 8.0 中有哪些新的变化?
  • .net 提取注释生成API文档 帮助文档
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .NET中winform传递参数至Url并获得返回值或文件
  • ??在JSP中,java和JavaScript如何交互?
  • @for /l %i in (1,1,10) do md %i 批处理自动建立目录
  • @vue/cli脚手架