spring boot3登录开发-1(整合jwt)

简介: spring boot3登录开发-1(整合jwt)

前置条件

已经初始化好一个spring boot项目且版本为3X,项目可正常启动。

作者版本为3.2.2

初始化教程:


jwt简介

  1. JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用间传输和存储信息的一种安全方式。
  2. 它由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。
  3. JWT可以被用作身份验证和授权,通过在服务器和客户端之间传递令牌来验证用户的身份并允许访问受保护的资源。
  4. 由于JWT是基于数字签名的,所以可以确保数据的完整性和安全性。它的设计简单、易于实现,并且可以跨不同的平台和语言使用。

导依赖

pom.xml:

 <dependency>
     <groupId>io.jsonwebtoken</groupId>
     <artifactId>jjwt</artifactId>
     <version>0.9.1</version>
 </dependency>
<!-- 如果jdk大于1.8,则还需导入下面依赖-->
 <dependency>
     <groupId>javax.xml.bind</groupId>
     <artifactId>jaxb-api</artifactId>
     <version>2.3.1</version>
 </dependency>

注意:你的jdk版本如果为1.8导入第一个就行,大于1.8就要导入两个。

编写jwt工具类

JWT(JSON Web Token)工具类在实际开发中通常包含以下一些常用方法:

  1. 生成JWT:用于生成JWT令牌并返回令牌字符串。
  2. 解析JWT:用于解析JWT令牌,验证签名,并获取其中的声明信息。
  3. 验证JWT:用于验证JWT的有效性,包括验证签名、过期时间等。
  4. 刷新JWT:用户还在操作,马上要快过期时,延长其有效期(无感刷新)。
  5. 其他辅助方法:例如获取JWT中的特定声明信息,验证JWT是否包含某个声明,等等。

其中生成和解析token是必须的,其他方法根据项目需求设计来决定写不写。

1.配置项直接嵌入代码,通过类名.静态方法使用

jwt工具类如下:

上面五种常用方法已经写好,cv过来直接能用。按需修改也可以。

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
 
 
/**
 * @author mijiupro
 */
public class JwtUtils {
 
    private static final String SIGN_KEY = "mijiu";// 加密密钥
 
    private static final long EXPIRE_TIME = 12 * 60 * 60 * 1000; //到期时间,12小时,单位毫秒
    private static final byte[] SECRET_KEY = SIGN_KEY.getBytes(StandardCharsets.UTF_8);
 
    /**
     * 生成token令牌
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @param subject 主题(用户类型)
     * @return token
     */
    public static String generateToken(Map<String,Object> claims, String subject) {
        return Jwts.builder()
                .setId(Claims.ID)//设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为令牌的唯一标识。
                .setSubject("mijiu")//设置主题,一般为用户类型
                .setIssuedAt(new Date())//设置签发时间
                .addClaims(claims)//设置负载
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)//设置签名算法
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE_TIME))//设置令牌过期时间
                .compact();//生成令牌
    }
 
    /**
     * 解析token令牌
     * @param token token令牌
     * @return 负载
     */
    public static Claims parseToken(String token) {
 
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
    }
 
    /**
     *  验证token令牌
     * @param token 令牌
     * @return 是否有效
     */
    public static boolean validateToken(String token) {
        try {
            Jwts.parser()
                    .setSigningKey(SECRET_KEY)
                    .parseClaimsJws(token)
                    .getBody();
 
            return true;
        } catch (Exception e) {
            return false;
        }
    }
 
    /**
     * 刷新Token
     * @param token 旧的Token令牌
     * @return 新的Token令牌
     */
    public static String refreshToken(String token) {
        try {
            // 解析旧的Token,获取负载信息
            Claims claims = parseToken(token);
            // 生成新的Token,设置过期时间和签名算法等参数
            return generateToken(claims, claims.getSubject());
        } catch (Exception e) {
            throw new RuntimeException("无法刷新令牌!", e);
        }
    }
 
 
    /**
     * 从令牌中获取主题信息
     * @param token 令牌
     * @return 主题信息(用户类型)
     */
    public static String getSubjectFromToken(String token) {
        try {
            Claims claims = parseToken(token); // 解析令牌,获取负载信息
            return claims.getSubject(); // 返回主题信息
        } catch (Exception e) {
            throw new RuntimeException("无法从令牌中获取主题。", e);
        }
    }
 
}

编写测试

测试代码如下:

import com.mijiu.commom.util.JwtUtils;
import io.jsonwebtoken.Claims;
import org.junit.jupiter.api.Test;
 
import java.util.Map;
 
public class JwtTest {
 
    @Test
    public void testJwt() {
        // 设置JWT的payload
    Map<String, Object> claims = Map.of("username", "mijiu", "role", "admin");
 
        // 生成JWT
        String jwt = JwtUtils.generateToken(claims, "secret");
 
        System.out.println("JWT: " + jwt);
 
        // 解析JWT
        Claims claims1 = JwtUtils.parseToken(jwt);
 
        // 获取完整的payload
        String payload = claims1.toString();
        System.out.println("Payload: " + payload);
    }
}

作者目录结构

运行测试代码

测试通过

2.配置项写到application.yml,交由spring容器管理依赖注入使用

jwt工具类如下:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
 
 
import java.util.Date;
import java.util.Map;
 
 
/**
 * @author mijiupro
 */
@Data
@Component
@ConfigurationProperties(prefix = "jwt")
public class JwtUtils {
 
    private String secret;//密钥
    private  long expiration;//过期时间
 
 
    /**
     * 生成token令牌
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @param subject 主题(用户类型)
     * @return token
     */
    public  String generateToken(Map<String,Object> claims, String subject) {
        return Jwts.builder()
                .setId(Claims.ID)//设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为令牌的唯一标识。
                .setSubject("mijiu")//设置主题,一般为用户类型
                .setIssuedAt(new Date())//设置签发时间
                .addClaims(claims)//设置负载
                .signWith(SignatureAlgorithm.HS256, secret)//设置签名算法
                .setExpiration(new Date(System.currentTimeMillis() + expiration))//设置令牌过期时间
                .compact();//生成令牌
    }
 
    /**
     * 解析token令牌
     * @param token token令牌
     * @return 负载
     */
    public  Claims parseToken(String token) {
 
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }
 
    /**
     *  验证token令牌
     * @param token 令牌
     * @return 是否有效
     */
    public  boolean validateToken(String token) {
        try {
            Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
 
            return true;
        } catch (Exception e) {
            return false;
        }
    }
 
    /**
     * 刷新Token
     * @param token 旧的Token令牌
     * @return 新的Token令牌
     */
    public  String refreshToken(String token) {
        try {
            // 解析旧的Token,获取负载信息
            Claims claims = parseToken(token);
            // 生成新的Token,设置过期时间和签名算法等参数
            return generateToken(claims, claims.getSubject());
        } catch (Exception e) {
            throw new RuntimeException("无法刷新令牌!", e);
        }
    }
 
 
    /**
     * 从令牌中获取主题信息
     * @param token 令牌
     * @return 主题信息(用户类型)
     */
    public  String getSubjectFromToken(String token) {
        try {
            Claims claims = parseToken(token); // 解析令牌,获取负载信息
            return claims.getSubject(); // 返回主题信息
        } catch (Exception e) {
            throw new RuntimeException("无法从令牌中获取主题。", e);
        }
    }
 
}

注意:此代码用到了lombok的@Data注解,来添加getter 和 setter 方法,请确保有该依赖


依赖坐标:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

配置文件添加jwt的配置项

application.yml:

jwt:
  secret: 123456 #密钥
  expiration: 43200000 #过期时间 12h

编写测试类

import com.mijiu.commom.util.JwtUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.HashMap;
import java.util.Map;
 
/**
 * @author mijiupro
 */
 
 
@RestController
@RequestMapping("/test")
public class TestController {
    private final JwtUtils jwtUtils;
    public TestController(JwtUtils jwtUtils) {
        this.jwtUtils = jwtUtils;
    }
 
    @GetMapping("/get-token")
    public String getToken() {
        Map<String, Object> claims = new HashMap<>();
        claims.put("username", "mijiu");
        claims.put("role", "admin");
        return jwtUtils.generateToken(claims,"user");
    }
    @GetMapping("/parse-token/{token}")
    public  String parseToken(@PathVariable String token) {
        return jwtUtils.parseToken(token).toString();
 
    }
}

目录结构

启动项目

请求jwt测试接口

生成token接口:

复制token

请求解析token接口并路径传参传入复制的token

测试成功。

目录
相关文章
|
3月前
|
前端开发 Java 关系型数据库
基于Java+Springboot+Vue开发的鲜花商城管理系统源码+运行
基于Java+Springboot+Vue开发的鲜花商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜花商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。技术学习共同进步
275 7
|
3月前
|
人工智能 Java 数据库
飞算 JavaAI:革新电商订单系统 Spring Boot 微服务开发
在电商订单系统开发中,传统方式耗时约30天,需应对复杂代码、调试与测试。飞算JavaAI作为一款AI代码生成工具,专注于简化Spring Boot微服务开发。它能根据业务需求自动生成RESTful API、数据库交互及事务管理代码,将开发时间缩短至1小时,效率提升80%。通过减少样板代码编写,提供规范且准确的代码,飞算JavaAI显著降低了开发成本,为软件开发带来革新动力。
|
26天前
|
Java API 微服务
Java 21 与 Spring Boot 3.2 微服务开发从入门到精通实操指南
《Java 21与Spring Boot 3.2微服务开发实践》摘要: 本文基于Java 21和Spring Boot 3.2最新特性,通过完整代码示例展示了微服务开发全流程。主要内容包括:1) 使用Spring Initializr初始化项目,集成Web、JPA、H2等组件;2) 配置虚拟线程支持高并发;3) 采用记录类优化DTO设计;4) 实现JPA Repository与Stream API数据访问;5) 服务层整合虚拟线程异步处理和结构化并发;6) 构建RESTful API并使用Springdoc生成文档。文中特别演示了虚拟线程配置(@Async)和StructuredTaskSco
118 0
|
2月前
|
供应链 JavaScript BI
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
这是一款专为小微企业打造的 SaaS ERP 管理系统,基于 SpringBoot+Vue+ElementUI+UniAPP 技术栈开发,帮助企业轻松上云。系统覆盖进销存、采购、销售、生产、财务、品质、OA 办公及 CRM 等核心功能,业务流程清晰且操作简便。支持二次开发与商用,提供自定义界面、审批流配置及灵活报表设计,助力企业高效管理与数字化转型。
219 2
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
|
3月前
|
人工智能 Java 定位技术
Java 开发玩转 MCP:从 Claude 自动化到 Spring AI Alibaba 生态整合
本文详细讲解了Java开发者如何基于Spring AI Alibaba框架玩转MCP(Model Context Protocol),涵盖基础概念、快速体验、服务发布与调用等内容。重点包括将Spring应用发布为MCP Server(支持stdio与SSE模式)、开发MCP Client调用服务,以及在Spring AI Alibaba的OpenManus中使用MCP增强工具能力。通过实际示例,如天气查询与百度地图路线规划,展示了MCP在AI应用中的强大作用。最后总结了MCP对AI开发的意义及其在Spring AI中的实现价值。
1168 9
|
7月前
|
JSON 安全 Java
什么是JWT?如何使用Spring Boot Security实现它?
什么是JWT?如何使用Spring Boot Security实现它?
1295 5
|
11月前
|
SQL Java 测试技术
在Spring boot中 使用JWT和过滤器实现登录认证
在Spring boot中 使用JWT和过滤器实现登录认证
545 0
|
9月前
|
JSON 安全 算法