全局过滤器实现Jwt校验

从Session到Jwt

之前我写过一篇 什么是 httpsession :
理解HttpSession

在经典的那个登录场景中:

客户端第一次访问的时候 需要登录 登录成功之后

后面再次访问的时候 为了让服务器认识 这是已经登录成功的我

在session中存储的用户的信息。

现在我们进化了! 使用Jwt
(jwt是一段token 它是登录的时候根据用户id生成的 也就说id一样 token就一样)

全局过滤器实现Jwt校验

在这里插入图片描述
为什么要进化 因为在分布式微服务中 会有很多个系统和服务相互配合 我们一般会用一个独立的网关服务来控制所有的请求入口

这时候jwt会比session更好用


如何实现全局过滤器的Jwt校验

创建一个过滤器实现 Ordered, GlobalFilter 接口

@Component
@Slf4j
public class AuthorizeFilter implements Ordered, GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return null;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

解释一下 这里面有2个方法重写 第一个是过滤用的 第二个是设置优先级用的(int值越小 代表优先级越高)

我们写一下拦截的逻辑 比如我们/login的请求就直接放行,其他请求 我们要验证一下 有没有token token是否有效 是否过期

   @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取每个请求的 req和resp对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        //2.判断是否是登录
        if(request.getURI().getPath().contains("/login")){
            //放行
            return chain.filter(exchange);
        }

        //3.获取token
        String token = request.getHeaders().getFirst("token");

        //4.判断token是否存在
        if(StringUtils.isBlank(token)){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        //5.判断token是否有效
        try {
            Claims claimsBody = AppJwtUtil.getClaimsBody(token);
            //是否是过期
            int result = AppJwtUtil.verifyToken(claimsBody);
            if(result == 1 || result  == 2){
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
        }catch (Exception e){
            e.printStackTrace();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        //6.放行
        return chain.filter(exchange);


    }

AppJwtUtil

public class AppJwtUtil {

    // TOKEN的有效期一天(S)
    private static final int TOKEN_TIME_OUT = 3_600;
    // 加密KEY
    private static final String TOKEN_ENCRY_KEY = "MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY";
    // 最小刷新间隔(S)
    private static final int REFRESH_TIME = 300;

    // 生产ID
    public static String getToken(Long id){
        Map<String, Object> claimMaps = new HashMap<>();
        claimMaps.put("id",id);
        long currentTime = System.currentTimeMillis();
        return Jwts.builder()
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(new Date(currentTime))  //签发时间
                .setSubject("system")  //说明
                .setIssuer("heima") //签发者信息
                .setAudience("app")  //接收用户
                .compressWith(CompressionCodecs.GZIP)  //数据压缩方式
                .signWith(SignatureAlgorithm.HS512, generalKey()) //加密方式
                .setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000))  //过期时间戳
                .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());
            // 需要自动刷新TOKEN
            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;
    }

}

然后我们启动测试项目 postman 请求一个带 /login的 或者不带的 试一下

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

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

相关文章

【leetcode】628.三个数的最大乘积

前言&#xff1a;剑指offer刷题系列 问题&#xff1a; 给你一个整型数组 nums &#xff0c;在数组中找出由三个数组成的最大乘积&#xff0c;并输出这个乘积。 示例&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;6思路1&#xff1a; 先去计算输入列表 nums …

蓝桥杯刷题(十三)

1.煤球数目 代码 cnt ans 0 start 1 a [] while cnt<100:ansstartstart 1t ansstartcnt1a.append(ans) print(sum(a))2.奖券数目 代码 def f(x)->bool:while x:if x%104:return Falsex//10return True ans 0 for i in range(10000,100000):if f(i):ans1 print(a…

鸿蒙实战开发:【国际化部件】

简介 国际化部件为应用提供了一系列国际化接口&#xff0c;包括&#xff1a;时间日期格式化、数字格式化、月份星期格式化、单复数、度量衡等相关接口。基于这些国际化接口&#xff0c;开发者可以设计并实现具有良好国际化能力的应用&#xff0c;从而可以高效、低成本的实现应…

(一)基于IDEA的JAVA基础4

注释文本&#xff0c;注释模版 单行注释://开头放在代码前面&#xff0c;对少部分。 多行注释:快捷方式ctrlshift/,对段落代码注 释。 文档注释:/**……**/&#xff0c;用于声明作者或创作时 间。 文档注释如何设置&#xff0c;首先找到File中…

[flask]flask的路由

路由的基本定义 路由就是一种映射关系。是绑定应用程序&#xff08;视图&#xff09;和url地址的一种一对一的映射关系&#xff01;在开发过程中&#xff0c;编写项目时所使用的路由往往是指代了框架/项目中用于完成路由功能的类&#xff0c;这个类一般就是路由类&#xff0c;…

vscode git图形化使用教程(一文秒懂,快速上手)

vscode git图形化使用教程&#xff08;一文秒懂&#xff0c;快速上手&#xff09; vscode 图形化 git  ​ 右键 checkout 功能&#xff0c;切换到当前分支 &#xff08;如果想要切换分支&#xff0c;必须要先上传当前更改的再切换分支&#xff0c;切换完分支后变为之前分支内…

网络编程3.21作业

1.现象 1.增 2.删 3.改 4.查 2.源码 #include<myhead.h>int callback(void* arg,int a,char **msgtext,char **msgheader){if(*(int *)arg0){for(int i0;i<a;i){printf("%s\t",*(msgheaderi));}printf("\n");}for(int i0;i<a;i){printf(&quo…

【Linux】深入了解Linux磁盘配额:限制用户磁盘空间的利器

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Linux ⛳️ 功不唐捐&#xff0c;玉汝于成 前言 在多用户环境下管理磁盘空间是服务器管理中的一项重要任务。Linux提供了强大的磁盘配额功能&#xff0c;可以帮助管理员限制用户或组对文件系统…

3.21总结​.Codeforces 第 935 轮(第 3 组)(A~D)题解​

一.Codeforces 第 935 轮&#xff08;第 3 组&#xff09;(A~D)题解 (直接给原文了,我电脑的翻译就是一坨.......) 这到题是一道思维题,理解题目意思就会觉得很简单首先内向的人肯定是一个人一个帐篷,我们只要关心外向的人就可以了,我们只要分外向的人可不可以被3整除,分成两种…

找不到msvcp110.dll无法继续执行程序的多种解决方法

在计算机操作系统中&#xff0c;msvcp110.dll文件扮演着至关重要的角色。作为Microsoft Visual C Redistributable Package的一部分&#xff0c;这个特定的dll文件包含了系统运行多种应用程序所必需的关键运行时库函数。许多Windows应用程序依赖于msvcp110.dll文件来执行基本操…

畅谈AIGC,ISIG-AIGC技术与应用发展峰会成功举办

3月16日&#xff0c;第四届ISIG中国产业智能大会在上海中庚聚龙酒店如期开幕&#xff0c;此次大会由苏州市金融科技协会指导、企智未来科技&#xff08;RPA中国、LowCode低码时代、AIGC开放社区&#xff09;主办。大会聚集了来自不同领域的专家学者、行业领军人物及技术研发者&…

亚信安慧AntDB:数字化创新背后的数据力量

亚信安慧AntDB的“融合实时”的特性&#xff0c;不仅使得数据库具备了更强大的适应性&#xff0c;更让企业在不同业务场景下能够更好地实现业务目标&#xff0c;释放出更大的商业价值。融合实时的特性让AntDB具有了高度灵活性和实时性&#xff0c;使其能够满足企业在不同业务需…

【机器学习】深入解析线性回归模型

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

基于springboot的学生心理健康评估系统

技术&#xff1a;springbootvuemysql 一、系统背景 这次开发的学生心理咨询评估系统有管理员和用户。管理员可以管理个人中心&#xff0c;用户管理&#xff0c;试题管理&#xff0c;试卷管理&#xff0c;考试管理等。用户参加考试。经过前面自己查阅的网络知识&#xff0c;加上…

智能模型新篇章:RAG + Fine-Tuning 混合增强策略

一、前言 在之前的探讨中&#xff0c;我们已经分别深入了解了RAG&#xff08;检索增强生成&#xff09;和 Fine-tuning&#xff08;微调&#xff09;这两种优化大型语言模型的方法&#xff0c;探讨了它们在不同业务场景下的适用性、优势及局限。然而&#xff0c;我们很少讨论将…

解读 Xend Finance:向 RWA 叙事拓展,构建更具包容性的 DeFi 体系

在二十世纪后&#xff0c;非洲地区陆续爆发了主权运动&#xff0c;这也让非洲大陆逐渐摆脱“殖民地”的标签。目前&#xff0c;非洲大陆公有 54 个主权国家&#xff0c;接近 15 亿且仍在飙升的人口规模&#xff0c;其 GDP 已经与印度相当&#xff0c;且仍旧处于飞速的发展进程中…

Python学习:字符串

Python 字符串概念 在Python中&#xff0c;字符串是一种不可变的数据类型&#xff0c;用于表示文本数据。字符串可以包含字母、数字、符号以及空格等字符&#xff0c;通常用引号&#xff08;单引号或双引号&#xff09;括起来表示。 var1 Hello World! var2 "www.csdn…

运维篇SHELL脚本实战案例

统计出每个IP的访问量有多少&#xff1f; 检查是否提供了日志文件的路径作为参数。使用awk从日志文件的每行中提取第一个字段&#xff08;假设这是IP地址&#xff09;。使用sort对提取的IP地址进行排序。使用uniq -c统计每个唯一IP地址的出现次数。最后&#xff0c;使用sort -…

Java的类与对象

前言 Java是一门纯面向对象的语言(Object Oriented Program&#xff0c;简称OOP)&#xff0c;在面向对象的世界里&#xff0c;一切皆为对象。面向对象是解决问题的一种思想&#xff0c;主要依靠对象之间的交互完成一件事情。用面向对象的思想来涉及程序&#xff0c;更符合人们…

2024年【熔化焊接与热切割】模拟考试题库及熔化焊接与热切割实操考试视频

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 熔化焊接与热切割模拟考试题库参考答案及熔化焊接与热切割考试试题解析是安全生产模拟考试一点通题库老师及熔化焊接与热切割操作证已考过的学员汇总&#xff0c;相对有效帮助熔化焊接与热切割实操考试视频学员顺利通…