java jwt生成token并在网关设置全局过滤器进行token的校验

news2024/9/25 1:20:02

1、首先引入jjwt的依赖

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

2、编写生成token的工具类

package com.jjw.result.util;

import com.jjw.result.constants.SystemConstants;
import io.jsonwebtoken.*;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.*;

public class AppJwtUtil {

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

    // 生产ID
    public static String createToken(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("jjw") //签发者信息
                .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 token
     * @return 1 有效  0 无效  2 已过期
     */
    public static Integer verifyToken(String token) {

        try {
            Claims claims = AppJwtUtil.getClaimsBody(token);
            if (claims == null) {
                return SystemConstants.JWT_FAIL;
            }
            return SystemConstants.JWT_OK;
        } catch (ExpiredJwtException ex) {
            return SystemConstants.JWT_EXPIRE;
        } catch (Exception e) {
            return SystemConstants.JWT_FAIL;
        }
    }

    /**
     * 由字符串生成加密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("id","11");*/
        String token = AppJwtUtil.createToken(1102L);
        System.out.println(token);	

        Claims claims = AppJwtUtil.getClaimsBody(token);
        //Integer integer = AppJwtUtil.verifyToken("dsafafsa");
        Integer integer = AppJwtUtil.verifyToken("eyJhbGciOiJIUzUxMiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAAAC2LywrDIBAA_2XP8aCrZs3frI-CQkFYQ1tK_z0b6G2GYb4wVocDMNuMXMhQfKDxJQXDuEcTk68tuFooBNig84LDRiJHO2HaQM6st3xktefdRVTHeCnzWZV5TuX2nv8vWX9_XZv7Xf0W2Rt-AAAA.srh9GIXr4ZqpXNfFb6vGIUxT12ve6Tu6xQ2KmdySsziP6AeCgP1h2GBhhx1g4rNbdsLozNI_WA-2FKsoR6-yPg");
        System.out.println(integer);
        System.out.println(claims);

    }
}

3、使用到的常量类:

package com.jjw.result.constants;

public class SystemConstants {
    //JWT TOKEN已过期
    public static final Integer JWT_EXPIRE = 2;
    //JWT TOKEN有效
    public static final Integer JWT_OK = 1;
    //JWT TOKEN无效
    public static final Integer JWT_FAIL = 0;

    public static final String USER_HEADER_NAME = "userId";

    public static final Integer TYPE_USER = 1; // 用户
    public static final Integer TYPE_E = 0; // 设备

}

4、在service的实现类中调用,生成token返回给前端

//4.生成令牌返回给前端
String token = AppJwtUtil.createToken(Long.valueOf(adUserFromDb.getId()));
Map<String, Object> info = new HashMap<>();
info.put("token",token);

5、在网关上进行校验,因此需要搭建网关服务。首先引人依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
    <groupId>com.jjw</groupId>
    <artifactId>result-content</artifactId>
    <version>1.0-SNAPSHOT</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </exclusion>
        <!--要排除spring-boot-starter-web这个依赖,但是result-content中包含的swagger-content这个
        依赖又依赖于spring-boot-starter-web,而我只需要result-content中的内容,所以将这两个依赖都排除了-->
        <exclusion>
            <groupId>com.jjw</groupId>
            <artifactId>swagger-content</artifactId>
        </exclusion>
    </exclusions>
</dependency>

6、启动类代码如下:

@SpringBootApplication
@EnableDiscoveryClient
public class GatewayAdminApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayAdminApplication.class,args);
    }
}

7、配置application.yml文件

spring:
  profiles:
    active: dev
---
server:
  port: 6001
spring:
  application:
    name: leadnews-admin-gateway
  profiles: dev
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
    gateway:
      globalcors:
        add-to-simple-url-handler-mapping: true  #增加
        cors-configurations:
          '[/**]': # 匹配所有请求
            allowedOrigins: "*" #跨域处理 允许所有的域
            allowedHeaders: "*"
            allowedMethods: # 支持的方法
              - GET
              - POST
              - PUT
              - DELETE
            allowCredentials: true # 是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期
      routes:
        # 平台管理
        - id: admin
          uri: lb://leadnews-admin
          predicates:
            - Path=/admin/**
          filters:
            - StripPrefix= 1

8、添加网关模块、结构如下:

在这里插入图片描述

9、编写校验token的AuthorizeFilter类(全局过滤器),其内容如下:

package com.jjw.gatewayadmin.filter;

import com.jjw.result.constants.SystemConstants;
import com.jjw.result.util.AppJwtUtil;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //+ 1.先获取请求和响应对象
        ServerHttpRequest request = exchange.getRequest();

        ServerHttpResponse response = exchange.getResponse();
        // /get /a  post /a

        //+ 2.判断当前的请求 是否 是登录的请求 如果是 ,则放行
        String path = request.getURI().getPath();
        if(path.equals("/admin/admin/login")){
            return chain.filter(exchange);
        }

        //+ 3.获取页面传递过来的请求头中的令牌数据 如果获取不到 返回错误(401)
        String token = request.getHeaders().getFirst("token");
        if(StringUtils.isEmpty(token)){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return  response.setComplete();//完成响应 返回 后面就不执行了
        }

        //+ 4.校验令牌 校验失败 返回错误401
        //通过jwt 来校验
        if(SystemConstants.JWT_OK!= AppJwtUtil.verifyToken(token)){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return  response.setComplete();//完成响应 返回 后面就不执行了
        }
        //+ 5.校验成功 放行
        return chain.filter(exchange);
    }


    //过滤器的执行的优先级的设置 值越低 优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【UnityDOTS 三】Component的理解

Component的理解 文章目录 Component的理解前言一、托管Component与非托管Component1.非托管Component2.托管Component 二、各功能的Component三、在Editor中的Component的区分总结 前言 Component作为ECS中承载数据的结构&#xff0c;了解他相关内容是非常必要的&#xff0c;…

基于Jsp+Servlet+Mysql学生信息管理系统

基于JspServletMysql学生信息管理系统 一、系统介绍二、功能展示1. 系统的部署2.导入数据库3. 系统介绍 四、其它1.其他系统实现五.获取源码 一、系统介绍 项目类型&#xff1a;Java web项目/Java EE项目/ 项目名称&#xff1a;基于sevelet的学生信息管理系统 当前版本&…

用Python制作一个简单时间、日期显示工具

Python是一款强大的编程软件&#xff0c;可以轻松实现我们的多种开发需求。今天我们拿Python中自带的tkinter来开发一个时钟显示器。如下图所示&#xff1a; 时间显示器 一、编程要求 用tkinter写一个漂亮、五彩的时间显示器&#xff0c;要求显示时、分、秒&#xff0c;即时变…

【JAVA】十分钟带你了解java的前世今生

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【初始JAVA】 文章目录 前言JAVA介绍诞生&#x1f52c;名字与图标&#x1f916;发展&#x1f6e9;️未来&#x1fa84; 前言 玩过我的世界的朋友想必对JAVA以及它的图标都很熟悉&#xff0c;在游戏开始画面…

Java程序所在机器性能监控

Java程序所在机器性能监控 背景 问题单&#xff1a;程序故障&#xff08;OOM、网络不通、操作卡顿&#xff09;问题单&#xff1a;服务连接不上需求 1、监控本地机器性能 告警日志UI2、监控服务接口服务 告警日志UI方案 固定间隔获取机器网络CPU内存数据设置阈值&#xff0c;告…

自定义starter实现接口或方法限流功能

本文的思路是利用AOP技术自定义注解实现对特定的方法或接口进行限流。目前通过查阅相关资料&#xff0c;整理出三种类型限流方法&#xff0c;分别为基于guava限流实现、基于sentinel限流实现、基于Semaphore的实现。 一、限流常用的算法 1.1令牌桶算法 令牌桶算法是目前应用…

OpenCV(视频加载与摄像头使用)

目录 1、VideoCapture类 2、视频属性get() 3、视屏文件保存 1、VideoCapture类 2、视频属性get() 3、视屏文件保存 //视频的读取保存 int test3() {VideoCapture video;//video.open("F:/testMap/lolTFT.mp4");//读取视频video.open(0);//读取摄像头if (!video.i…

linux docker安装

一、Linux安装docker 1.1 前提 要求Linux内核&#xff08;kernel&#xff09; 版本大于等于3.8。&#xff08;kernel version >3.8&#xff09;。 查看当前系统内核版本 uname -a | awk {split($3,arr,"-");print arr[1]} 1.2 linux 安装docker Centos安装doc…

【数据结构与算法】7、队列(Queue)的实现【用栈实现队列】

目录 一、队列介绍二、使用 LinkedList 实现队列三、LeetCode&#xff1a;用【栈】实现队列(1) 老师讲之前我自己的实现&#xff08;Correct&#xff09;(2) 实现思路(3) 代码实现 四、jdk 的 Queue五、双端队列&#xff08;Deque&#xff09;六、循环队列(1) 分析(2) 入队(3) …

Linux--运行指令的本质

本质&#xff1a; ①找到它 which的作用就是找到它 ②运行它 示例&#xff1a; ①告诉系统要运行的指令&#xff0c;然后系统去查找它的路径并运行它 ②自己告诉系统自己要运行的路径&#xff0c;然后系统运行它 注意&#xff1a;a.out不能运行&#xff0c;而./a.out能运行…

MES是如何帮助企业提高生产效率的

大多数提高制造生产效率的系统都是从详细分析公司的制造流程和运营开始的。这样做的目的是是为了消除浪费的不增值的流程&#xff0c;将有价值的流程系统化&#xff0c;实现生产自动化并增强增值操作。 在自动化流程方面&#xff0c;实施制造执行系统&#xff08;MES&#xff…

HTML5 游戏开发实战 | 俄罗斯方块

俄罗斯方块是一款风靡全球的电视游戏机和掌上游戏机游戏&#xff0c;它曾经造成的轰动与造成的经济价值可以说是游戏史上的一件大事。这款游戏看似简单但却变化无穷&#xff0c;游戏过程仅需要玩家将不断下落的各种形状的方块移动、翻转&#xff0c;如果某一行被方块充满了&…

发送邮箱验证码【spring boot】

⭐前言⭐ ※※※大家好&#xff01;我是同学〖森〗&#xff0c;一名计算机爱好者&#xff0c;今天让我们进入学习模式。若有错误&#xff0c;请多多指教。更多有趣的代码请移步Gitee &#x1f44d; 点赞 ⭐ 收藏 &#x1f4dd;留言 都是我创作的最大的动力&#xff01; 1. 思维…

Redis6之穿透、击穿、雪崩

大量的高并发的请求打在Redis上&#xff0c;但是发现Redis中并没有请求的数据&#xff0c;redis的命令率降低&#xff0c;所以这些请求就只能直接打在DB&#xff08;数据库服务器&#xff09;上&#xff0c;在大量的高并发的请求下就会导致DB直接卡死、宕机。 缓存穿透 当客户端…

一例Phorpiex僵尸网络样本分析

本文主要分析Phorpiex僵尸网络的一个变种&#xff0c;该样本通常NSIS打包&#xff0c;能够检测虚拟机和沙箱。病毒本体伪装为一个文件夹&#xff0c;通过U盘来传播&#xff0c;会隐藏系统中各盘符根目录下的文件夹&#xff0c;创建同名的lnk文件&#xff0c;诱导用户点击。 病…

TF卡/U盘系统备份

Jetson nano使用TF卡/U盘来装载系统&#xff0c;如果TF卡/U盘丢失或者损坏&#xff0c;那么Jetson nano上的数据都会丢失&#xff0c;所以一定要备份好TF卡/U盘。这篇文章可以帮你备份你的Jetson nano系统。主要内容为备份TF卡/U盘&#xff0c;制作Jetson nano系统镜像以及在需…

Java——《面试题——ElasticSearch篇》

目录 1、谈谈分词与倒排索引的原理 2、说说分段存储的思想 3、谈谈你对段合并的策略思想的认识 4、了解文本相似度 TF-IDF吗 5、能说说ElasticSearch 写索引的逻辑吗&#xff1f; 6、熟悉ElasticSearch 集群中搜索数据的过程吗&#xff1f; 7、了解ElasticSearch 深翻页的…

vsCode 创建新java项目(创建一个新java项目测试方法)

VSCODE环境配置-java之项目建立&#xff0c;非常适合刚准备使用VSCODE开发JAVA的人_vscode创建java项目_rainmenzhao的博客-CSDN博客 1 按 ctrl shift p 2 输入 create Java project 3 选 no build tools 4 选择 一个文件夹 存放 之后要 新建的文件 5 选完之后 自动返回主页…

获得Jolt 大奖的《持续交付》作者David Farley又一新作《现代软件工程》

戴维 法利 (David Farley) 是持续交付的先驱、思想领袖&#xff0c; 也是持续交付、 DevOps、 测试驱动开发和软件开发领域的专家。 从现代计算的早期开始&#xff0c;戴维曾担任过程序员、软件工程师、系统架构师和成功团 队的领导者&#xff0c;他掌握了计算机和软件开发的基…

ES基本操作(postman篇)

关系型数据库 -> Databases(库) -> Tables(表) -> Rows(行) -> Columns(列)。Elasticsearch -> Indeces(索引) -> Types(类型) -> Documents(文档) -> Fields(属性)。 需要注意的是&#xff1a;type的概念在es7.0之后已经删除了。 以下仅做刚入门学习…