基于Spring Boot 3与JWT构建现代化登录认证机制

Spring Boot 3 整合 JWT(JSON Web Tokens)用于登录开发涉及多个步骤。JWT 是一种开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。这些信息可以被验证和信任,因为它们是数字签名的。

以下是一个简单的步骤指南,用于在 Spring Boot 3 应用中整合 JWT:

第一种方式

1. 添加依赖

首先,在你的 pom.xml 文件中添加 Spring Boot Web 和 JWT 相关的依赖:

<dependencies>  
    <!-- Spring Boot Web Starter -->  
    <dependency>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-web</artifactId>  
    </dependency>  
    <!-- JWT Library, 例如 jjwt -->  
    <dependency>  
        <groupId>io.jsonwebtoken</groupId>  
        <artifactId>jjwt</artifactId>  
        <version>你的jjwt版本号</version>  
    </dependency>  
    <!-- 如果jdk大于1.8 则需要导入以下依懒 -->  
     <dependency>  
        <groupId>javax.xml.bind</groupId>  
        <artifactId>jaxb.api</artifactId>  
        <version>2.3.1</version>  
    </dependency>  

    <!-- 其他依赖 -->  
</dependencies>

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

2. 配置 JWT

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

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

创建一个工具类,用于生成和验证 JWT,配置 JWT 的密钥和有效期等:

​
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 Yun
 */
public class JwtUtils {
 
    private static final String SIGN_KEY = "你的密钥";// 加密密钥
 
    private static final long EXPIRE_TIME = 2 * 60 * 60 * 1000; //到期时间,2小时,单位毫秒
    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的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为令牌的唯一标识。
                .setIssuedAt(new Date())//设置签发时间
                .setSubject("yun")//设置主题,一般为用户类型
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)//设置签名算法,使用HS256算法 
                .addClaims(claims)//设置负载
                .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);
        }
    }
 
}

​

3.  编写测试登录接口

在你的 test目录下创建JwtTest.java文件中,测试代码如下:

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> claim = Map.of("username", "yun", "role", "admin");
 
        // 生成JWT
        String jwt = JwtUtils.generateToken(claim, "secret");
 
        System.out.println("JWT: " + jwt);
 
        // 解析JWT
        Claims claims = JwtUtils.parseToken(jwt);
 
        // 获取完整的payload
        String payload = claims1.toString();

        System.out.println("Payload: " + payload);
    }
}

第二种方式:交由spring容器管理依赖注入使用

配置文件

application.propertiesapplication.yml文件中配置JWT相关的属性,如密钥、过期时间等。

jwt:  
  secret: your-secret-key  你的密钥
  expiration: 86400000 # 1天,单位:毫秒
注意:此代码用到了lombok的@Data注解,来添加getter 和 setter 方法,请确保有该依赖
​
        <!--lombok-->
        <!-- ClassFormatException: Invalid byte tag in constant pool: 19
            lombok  版本过高 1.18.x 导致
        -->
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
            <scope>provided</scope>
        </dependency>

​

jwt工具类如下:

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

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 yun
 */
@Data
@Component
@ConfigurationProperties(prefix = "jwt")
public class JwtUtils {
 
    private String secret; //在application.yml中配置的密钥
    private  long expiration; //在application.yml设置的过期时间
 
 
    /**
     * 生成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("yun")//设置主题,一般为用户类型
                .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);
        }
    }
 
}

创建登录接口

在你的 Controller 中,创建处理登录请求的接口:

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 yun
 */
 
 
@RestController
@RequestMapping("/api/auth")
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", "yun");
        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接口:localhost:8080/api/auth/get-token

复制token

请求解析token接口并路径传参传入复制的token:localhost:8080/api/auth/parse-token/你的token

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
针对你的问题,我可以提供以下的一些思路: 1. 首先,你需要使用Spring Security来实现用户认证和授权。在Spring Security中,你可以配置多个AuthenticationProvider实现不同的认证方式。具体而言,你需要实现一个自定义的AuthenticationProvider,用于验证JWT令牌是否有效。在进行认证时,该AuthenticationProvider会获取到请求头中的JWT令牌,然后进行解析和验证,如果解析和验证成功,就会把该用户的信息构建成一个Authentication对象返回给Spring Security框架。 2. 其次,你需要使用JWT来生成令牌并将其发送给客户端。JWT(Json Web Token)是一种轻量级的身份认证机制,可以在不依赖于Session的情况下实现用户的身份认证和授权。在使用JWT时,你需要创建一个私钥和公钥对,私钥用于对JWT进行签名,公钥用于对JWT进行验证。当用户登录成功后,你需要使用私钥对用户的信息进行签名,生成一个JWT令牌,并将该令牌发送给客户端。客户端在以后的请求中需要将该令牌作为Authorization请求头的值发送给服务端。 3. 最后,你需要在服务端验证JWT令牌的有效性。在服务端接收到请求后,你需要从请求头中获取JWT令牌,并使用公钥对该令牌进行验证,验证成功后就可以获得该用户的信息。在接下来的业务逻辑中,你可以使用该用户的信息来进行权限判断等操作。 希望以上的思路对你有所帮助。如果你需要更加详细的实现步骤,可以参考Spring Security和JWT相关的官方文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值