mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-18 09:35:29 +08:00
feat sa-token-jwt支持使用rs256生成token
This commit is contained in:
parent
c19f2b9e4e
commit
5437f2d265
@ -104,6 +104,11 @@ sa-token:
|
|||||||
is-share: false
|
is-share: false
|
||||||
# jwt秘钥
|
# jwt秘钥
|
||||||
jwt-secret-key: abcdefghijklmnopqrstuvwxyz
|
jwt-secret-key: abcdefghijklmnopqrstuvwxyz
|
||||||
|
rsa:
|
||||||
|
enabled: false
|
||||||
|
publicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxRyMohAfHyH3GzUulXNUkaoPHOKF7X4JgixkW7GtmAQuMazR7ruF5QgpA+37qWAHaqGWNX2GoU1gAM4XUlw+g0K++4I6Vh759ZjpNn92nYfowOzsInhRLVFgojKhkCbRuf6py6i9Lvqf1cZ5BiRPoQP0vVrEnO8Xf9RgNdj6Hg92Pm/DRpxp1+EBPvs9fNWfgGAGd7L4r10qVCB9uLoEmt9/I6l2hhmAecmMbyn2BQwJqUthXC6lOhyDkjiWrG7Q3VrJ1bufl2ZG56ViHT8UQL/gSaNizuGecSPF7FYyslWx5FayhKTtIbtHsFgEfOuR+eVcGT9HeABrBiF69IM8bwIDAQAB
|
||||||
|
privateKey: MIIEugIBADANBgkqhkiG9w0BAQEFAASCBKQwggSgAgEAAoIBAQDFHIyiEB8fIfcbNS6Vc1SRqg8c4oXtfgmCLGRbsa2YBC4xrNHuu4XlCCkD7fupYAdqoZY1fYahTWAAzhdSXD6DQr77gjpWHvn1mOk2f3adh+jA7OwieFEtUWCiMqGQJtG5/qnLqL0u+p/VxnkGJE+hA/S9WsSc7xd/1GA12PoeD3Y+b8NGnGnX4QE++z181Z+AYAZ3svivXSpUIH24ugSa338jqXaGGYB5yYxvKfYFDAmpS2FcLqU6HIOSOJasbtDdWsnVu5+XZkbnpWIdPxRAv+BJo2LO4Z5xI8XsVjKyVbHkVrKEpO0hu0ewWAR865H55VwZP0d4AGsGIXr0gzxvAgMBAAECggEATfwqo9/vADlG8+vJn3V+yxbWXd49kKXiCy+XETQt80wMHrk6YdKted0NpTFd9Tg6FvURYd5lCqJ7TjY7wekfDn204/s1K2ecC5BRDK/HdTIVY2cZUdX6gAyHSATyKP9C0OyxrxL2roSYAlNBBK4PFyxigxxLV6+8w2V6HzPWWVega1inzqbafwMkC2DAFjtQqxHXHf8bo93GNCh/GfPKSzZnzeNSQo0JHOOu8VKyapsJe7enJqsyKWdVMUK2G/ikIebNqV+0y8aFSwUeoqx/FaBtF2fSNaUUqM3Zwo+oF5E7UdnI7FlFK+Q0LiMz0pGER88/p4rStcFCoAKIAG8boQKBgQDPrq9kN4MBqFOWRBXAuGbZQIh0VAInfXcdLPrIiIbxRGw8yOP/JTLqz+VhVuDzGoaKVxhRm0rG0P78q3ICyyKUOENrmtURvLVjSad1EH2PNyI6OOevk/BU2rUgsJkwMVBKawPsrmL8EEPGuaQHtS3KoLcS83UIYVbcwYKxjUyiHwKBgQDy+EcCbSdlTdtJXep6hDRB6AaLmFvr/aVhvI9jFDrkgm2U/VnHXyuFo+uJDCAFUniVGoYL3sNCcu8oLEYEI/kxbvy8F4+jsFeQ/lv7DUwzKJo8QcELlwvDntbNHd43a/LdFOcg4q+Y48zJenS9mrx/JyYEcVMTULdu/0oqBZY7sQKBgH3/LMlQJFrNFGkFxWy2cy86x45LqULsC2fX8g3XRob5S/FUr34Lw2hR2IfFfZP/c8BaNpbL8AHOqeQA35pyQvhJah3OQZYRNrqV5NJQvtw0Rr+r5mPPDO9uAJVkjot+X4fGhQsCgWsLMxNNbQaAFNfpySfmLAp5g4lKnU+6udNhAoGAIhQAoa59oA/Tee7aPGTej3/jqyCrg+YHlDXGRrdHq1U/2W3Pcc8/Y3ciSg6RTy3KC9+0fWW5LVDBinjrORlykiRm/lqvot3Q6l1CuWucDHDdcSYn1WBSHhXhOtO9nzhcz/VmlY414tPQnVG3ngBd/9eV1XmvlT30/HSCCnLOJ4ECf1Eq6JZ3uC/p2nG+Kpy7JrYL/TeIFlSZ0e6gaoGpjmzQasCnP4mgwLKwl8eYooBy0iqbN4Cpj73E+/FwirlTUS/QUoN1TLIMWYR+FEAYV1Pd6C6FgbDWp3aOdBY4zN17VHViIlc6Qoeh1Hw9b5wQ0usHGdNjJhBitiqzdfp3oX8=
|
||||||
|
|
||||||
|
|
||||||
# security配置
|
# security配置
|
||||||
security:
|
security:
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
package org.dromara.common.satoken.config;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.jwt.SaJwtUtil;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import org.dromara.common.satoken.core.CustomSaJwtTemplate;
|
||||||
|
import org.dromara.common.satoken.properties.SaTokenRsaProperties;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sa-token RSA密钥自动配置
|
||||||
|
*
|
||||||
|
* @author T
|
||||||
|
*/
|
||||||
|
@AutoConfiguration
|
||||||
|
@EnableConfigurationProperties(SaTokenRsaProperties.class)
|
||||||
|
@ConditionalOnProperty(value = "sa-token.rsa.enabled", havingValue = "true")
|
||||||
|
public class SaTokenRsaConfig {
|
||||||
|
@Autowired
|
||||||
|
SaTokenRsaProperties properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义 SaJwtUtil 生成 token 的算法
|
||||||
|
*/
|
||||||
|
@PostConstruct
|
||||||
|
public void setSaJwtTemplate() {
|
||||||
|
SaJwtUtil.setSaJwtTemplate(new CustomSaJwtTemplate(properties));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,107 @@
|
|||||||
|
package org.dromara.common.satoken.core;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.jwt.SaJwtTemplate;
|
||||||
|
import cn.dev33.satoken.jwt.exception.SaJwtException;
|
||||||
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import cn.hutool.json.JSONException;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import cn.hutool.jwt.JWT;
|
||||||
|
import cn.hutool.jwt.JWTException;
|
||||||
|
import cn.hutool.jwt.signers.JWTSigner;
|
||||||
|
import cn.hutool.jwt.signers.JWTSignerUtil;
|
||||||
|
import org.dromara.common.satoken.properties.SaTokenRsaProperties;
|
||||||
|
|
||||||
|
import java.security.Key;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义 jwt 模版
|
||||||
|
*
|
||||||
|
* @author T
|
||||||
|
*/
|
||||||
|
public class CustomSaJwtTemplate extends SaJwtTemplate {
|
||||||
|
private PublicKey publicKey;
|
||||||
|
private PrivateKey privateKey;
|
||||||
|
|
||||||
|
public CustomSaJwtTemplate(SaTokenRsaProperties properties) {
|
||||||
|
this.publicKey = SecureUtil.rsa(null,properties.getPublicKey()).getPublicKey();
|
||||||
|
this.privateKey = SecureUtil.rsa(properties.getPrivateKey(),null).getPrivateKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generateToken(JWT jwt, String keyt) {
|
||||||
|
return jwt.setSigner(this.createSigner(privateKey)).sign();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JWTSigner createSigner(Key key) {
|
||||||
|
if (SaFoxUtil.isEmpty(key)) {
|
||||||
|
throw new SaJwtException("请配置 RSA 密钥");
|
||||||
|
}
|
||||||
|
return JWTSignerUtil.rs256(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JWT parseToken(String token, String loginType, String keyt, boolean isCheckTimeout) {
|
||||||
|
if (SaFoxUtil.isEmpty(keyt)) {
|
||||||
|
throw new SaJwtException("请配置 jwt 秘钥");
|
||||||
|
} else if (token == null) {
|
||||||
|
throw new SaJwtException("jwt 字符串不可为空");
|
||||||
|
} else {
|
||||||
|
JWT jwt;
|
||||||
|
try {
|
||||||
|
jwt = JWT.of(token);
|
||||||
|
} catch (JSONException | JWTException e) {
|
||||||
|
throw (new SaJwtException("jwt 解析失败:" + token, e)).setCode(30201);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject payloads = jwt.getPayloads();
|
||||||
|
boolean verify = jwt.setSigner(this.createSigner(publicKey)).verify();
|
||||||
|
if (!verify) {
|
||||||
|
throw (new SaJwtException("jwt 签名无效:" + token)).setCode(30202);
|
||||||
|
} else if (!Objects.equals(loginType, payloads.getStr("loginType"))) {
|
||||||
|
throw (new SaJwtException("jwt loginType 无效:" + token)).setCode(30203);
|
||||||
|
} else {
|
||||||
|
if (isCheckTimeout) {
|
||||||
|
Long effTime = payloads.getLong("eff", 0L);
|
||||||
|
if (effTime != -1L && (effTime == null || effTime < System.currentTimeMillis())) {
|
||||||
|
throw (new SaJwtException("jwt 已过期:" + token)).setCode(30204);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return jwt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimeout(String token, String loginType, String keyt) {
|
||||||
|
if (token == null) {
|
||||||
|
return -2L;
|
||||||
|
} else {
|
||||||
|
JWT jwt;
|
||||||
|
try {
|
||||||
|
jwt = JWT.of(token);
|
||||||
|
} catch (JWTException var8) {
|
||||||
|
return -2L;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject payloads = jwt.getPayloads();
|
||||||
|
boolean verify = jwt.setSigner(this.createSigner(publicKey)).verify();
|
||||||
|
if (!verify) {
|
||||||
|
return -2L;
|
||||||
|
} else if (!Objects.equals(loginType, payloads.getStr("loginType"))) {
|
||||||
|
return -2L;
|
||||||
|
} else {
|
||||||
|
Long effTime = (Long) payloads.get("eff", Long.class);
|
||||||
|
if (effTime == -1L) {
|
||||||
|
return -1L;
|
||||||
|
} else {
|
||||||
|
return effTime != null && effTime >= System.currentTimeMillis() ? (effTime - System.currentTimeMillis()) / 1000L : -2L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package org.dromara.common.satoken.properties;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sa-token RSA密钥配置类
|
||||||
|
*
|
||||||
|
* @author T
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ConfigurationProperties(prefix = "sa-token.rsa")
|
||||||
|
public class SaTokenRsaProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rsa开关
|
||||||
|
*/
|
||||||
|
private Boolean enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公钥
|
||||||
|
*/
|
||||||
|
private String publicKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私钥
|
||||||
|
*/
|
||||||
|
private String privateKey;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package org.dromara.common.satoken.utils;
|
||||||
|
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSA工具类
|
||||||
|
* 生成密钥对
|
||||||
|
*
|
||||||
|
* @author T
|
||||||
|
*/
|
||||||
|
public class RSAUtil {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
generateKeys();
|
||||||
|
}
|
||||||
|
public static void generateKeys() throws Exception {
|
||||||
|
KeyPair keyPair = SecureUtil.generateKeyPair("RSA", 2048);
|
||||||
|
PublicKey publicKey = keyPair.getPublic();
|
||||||
|
PrivateKey privateKey = keyPair.getPrivate();
|
||||||
|
|
||||||
|
String publicKeyBase64String = Base64.getEncoder().encodeToString(publicKey.getEncoded());
|
||||||
|
String privateKeyBase64String = Base64.getEncoder().encodeToString(privateKey.getEncoded());
|
||||||
|
|
||||||
|
// 保存到配置文件
|
||||||
|
System.out.println("sa-token.ras.publicKey: " + publicKeyBase64String);
|
||||||
|
System.out.println("sa-token.ras.privateKey: " + privateKeyBase64String);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1 +1,2 @@
|
|||||||
org.dromara.common.satoken.config.SaTokenConfig
|
org.dromara.common.satoken.config.SaTokenConfig
|
||||||
|
org.dromara.common.satoken.config.SaTokenRsaConfig
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user