关于SpringBoot2.x集成SpringSecurity+JJWT(0.7.0-->0.11.5)生成Token登录鉴权的问题

项目场景:

问题:遵循版本稳定的前提下,搭建权限认证框架,基于SpringBoot2.x+SpringSecurity向上依赖+jjwt0.7.0构建用户认证鉴权,起因是某L觉得jjwt0.7.0版本,官方已经放弃维护,且从maven仓库对0.7.0版本使用量对比来看,遂放弃0.7.0转而升级为0.11.5,由此引发的token生成和解析的一系列BUG
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.7.14</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>cn.isungent.ird</groupId>
	<artifactId>epdx</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>epdx</name>
	<description>Enterprise Data Platform</description>
	<properties>
		<java.version>1.8</java.version>
		<mybatis-plus.version>3.5.3.2</mybatis-plus.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<!-- NOTE: cannot exclude jackson because swagger needs it. -->
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.3.1</version>
		</dependency>
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>com.mysql</groupId>
			<artifactId>mysql-connector-j</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
<!--		<dependency>-->
<!--			<groupId>org.mybatis.spring.boot</groupId>-->
<!--			<artifactId>mybatis-spring-boot-starter-test</artifactId>-->
<!--			<version>2.3.1</version>-->
<!--			<scope>test</scope>-->
<!--		</dependency>-->
		<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter-test -->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter-test</artifactId>
			<version>${mybatis-plus.version}</version>
			<scope>test</scope>
		</dependency>

		<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
		<dependency>
			<groupId>com.google.code.gson</groupId>
			<artifactId>gson</artifactId>
			<version>2.10.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.12.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-core</artifactId>
			<version>4.11.0</version>
			<scope>test</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger2</artifactId>
			<version>3.0.0</version>
		</dependency>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-boot-starter</artifactId>
			<version>3.0.0</version>
		</dependency>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger-ui</artifactId>
			<version>3.0.0</version>
		</dependency>

		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>${mybatis-plus.version}</version>
		</dependency>

		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-extension</artifactId>
			<version>${mybatis-plus.version}</version>
		</dependency>

		<dependency>
			<groupId>org.mariadb.jdbc</groupId>
			<artifactId>mariadb-java-client</artifactId>
			<scope>runtime</scope>
			<version>2.7.10</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt-api</artifactId>
			<version>0.11.5</version>
		</dependency>
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt-impl</artifactId>
			<version>0.11.5</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
			<version>0.11.5</version>
			<scope>runtime</scope>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

yml配置

spring:
  datasource:
    driverClassName: org.h2.Driver
    url: jdbc:h2:mem:test-db
  sql:
    init:
      data-locations: classpath:db/data.sql
      encoding: utf8
      schema-locations: classpath:db/schema.sql

  h2:
    console:
      enabled: true
      path: /h2-console


jwt:
  secret: kiki
  expiration: 18000
  tokenHeader: Authorization
  loginFailMaxNum: 5
  tokenPrefix: authorization-
  authUserName: AuthorizationUserName
  authRole: admin
  authEmail: admin@example.com

JwtTokenUtil

package cn.isungent.ird.epdx.common.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author kiki
 * @date 2023/10/10
 * @description
 */
@Component
@ConfigurationProperties(prefix = "jwt")
public class JwtTokenUtil {

    private static final String CLAIM_KEY_USERNAME = "sub";
    private static final String CLAIM_KEY_CREATED = "$2a$10$khMzocJpIzuhkiqSFLQ/euwedqw/ocRjZUI0SsS/TDY0e4RZIxh0C";

    private String secret;

    private Integer expiration;

    public Claims getClaimsFromToken(String token, String secret) {
        Claims claims = Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
        return claims;
    }

    private String generateToken(Map<String, Object> claims) {
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(generateExpirationDate())
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }

    public String generateToken(String userEmail) {
        Map<String, Object> claims = new HashMap<>(16);
        claims.put(CLAIM_KEY_USERNAME, userEmail);
        claims.put(CLAIM_KEY_CREATED, new Date());
        return generateToken(claims);
    }

    private Date generateExpirationDate() {
        return new Date(System.currentTimeMillis() + expiration * 1000);
    }

    public String getSecret() {
        return secret;
    }

    public void setSecret(String secret) {
        this.secret = secret;
    }

    public Integer getExpiration() {
        return expiration;
    }

    public void setExpiration(Integer expiration) {
        this.expiration = expiration;
    }
}

如下,升级版本后,postman模拟登录报错


在这里插入图片描述
consul打印

io.jsonwebtoken.security.WeakKeyException: The signing key's size is 24 bits which is not secure enough for the HS512 algorithm.  The JWT JWA Specification (RFC 7518, Section 3.2) states that keys used with HS512 MUST have a size >= 512 bits (the key size must be greater than or equal to the hash output size).  Consider using the io.jsonwebtoken.security.Keys class's 'secretKeyFor(SignatureAlgorithm.HS512)' method to create a key guaranteed to be secure enough for HS512.  See https://tools.ietf.org/html/rfc7518#section-3.2 for more information.
	at io.jsonwebtoken.SignatureAlgorithm.assertValid(SignatureAlgorithm.java:387)

问题描述

翻译:The signing key's size is 24 bits which is not secure enough for the HS512 algorithm. The JWT JWA Specification (RFC 7518, Section 3.2) states that keys used with HS512 MUST have a size >= 512 bits (the key size must be greater than or equal to the hash output size). Consider using the io.jsonwebtoken.security.Keys class's 'secretKeyFor(SignatureAlgorithm.HS512)' method to create a key guaranteed to be secure enough for HS512. See https://tools.ietf.org/html/rfc7518#section-3.2 for more information.大概意思是说:io.jsonwebtoken.security.WeakKeyException:签名密钥的大小是24位,对于HS512算法来说不够安全。JWT JWA规范(RFC 7518, Section 3.2)规定,与HS512一起使用的密钥的大小必须大于= 512位(密钥大小必须大于或等于哈希输出的大小)。考虑使用io.jsonwebtoken.security.Keys类的'secretKeyFor(signaturealalgorithm .HS512)'方法来创建一个保证对HS512足够安全的密钥。参见https:tools.ietf.orghtmlrfc7518section-3.2获取更多信息

综上:就是说升级后,那个密钥的长度要大于512,就是yml中配置secrect的配置项,太短了


解决方案:

提示:修改yml配置项jwt.secrect的密钥字符串的值为AAAAB3NzaC1yc2EAAAADAQABAAABgQDb73eBHCS6avoS2hnC3Zzf3N1JQax2Wg2Z9uvxIq6MlORGGFnrhV3jlDD2+iXsoM1UUEOIvhGMeeAt9EWJ8MVIbKOfHzChwkHojUlTFd87qWxCEfS9LWcl1d1Hsx9R1R5Uj31xfP76XlQAR+vhOGQtk1RW1RInxWZVo/++Bts9iNCvxMCx5c/v9Dhgrkj+CD2b1YoYILn6xZjjRMOVB33+xV5ERO5mluHQV+8xKght75WQqaOz4lARBsfxgOpMAzVU6IYCz2qGztrYNCjnjgBLee+Kok4belJM7fjW5ntuP7kPGLAnxfkZQWdR/iG71PuZmcNngesxaqIxVD3Hwa6Qfv2cUsS2bJn/L51uT5k07obZF5poxssCx7qzhe+1Aa1sDfct2vfkqzYCikI9ioKqM999dKiqYPP13ThfYfaWRuVKor3/tgZkbKmhf7+BH8pLnS03/ewZZgwxxx=

注意:值可以是任意字符串,非固定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慕木兮人可

感谢支持,勿忘初心

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值