forked from fanruan/finekit
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
7.0 KiB
214 lines
7.0 KiB
6 years ago
|
package com.fanruan.api.security;
|
||
|
|
||
|
import com.fanruan.api.log.LogKit;
|
||
|
import com.fr.cert.token.JwtBuilder;
|
||
|
import com.fr.cert.token.Jwts;
|
||
|
import com.fr.cert.token.SignatureAlgorithm;
|
||
|
import com.fr.cert.token.SignatureException;
|
||
|
import com.fr.cert.token.impl.DefaultClaims;
|
||
|
import com.fr.security.KeySecretSeedConfig;
|
||
|
import com.fr.security.SecurityToolbox;
|
||
|
|
||
|
import java.io.IOException;
|
||
|
import java.security.Key;
|
||
|
import java.util.Date;
|
||
|
import java.util.Map;
|
||
|
|
||
|
/**
|
||
|
* @author richie
|
||
|
* @version 10.0
|
||
|
* Created by richie on 2019-09-03
|
||
|
* 用于生成和解析基于JWT的token
|
||
|
*/
|
||
|
public class JwtKit {
|
||
|
|
||
|
private static final String JWT_ID = "jwt";
|
||
|
private static final String ISSUER = "fanruan";
|
||
|
private static final SignatureAlgorithm DEFAULT_ALGORITHM = SignatureAlgorithm.HS256;
|
||
|
|
||
|
/**
|
||
|
* 创建完整token
|
||
|
*
|
||
|
* @param issuer jwt签发者
|
||
|
* @param subject jwt所面向的用户
|
||
|
* @param audience 接收jwt的一方
|
||
|
* @param expiration jwt的过期时间,这个过期时间必须要大于签发时间
|
||
|
* @param notBeforeTime 定义在什么时间之前,该jwt都是不可用的.
|
||
|
* @param issuerAtTime jwt的签发时间
|
||
|
* @param jwtId jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
|
||
|
* @param algorithm 加密算法
|
||
|
* @param secretKey 秘钥
|
||
|
* @return 签名后的token
|
||
|
*/
|
||
|
public static String createJWT(String issuer, String subject, String audience, Date expiration, Date notBeforeTime,
|
||
|
Date issuerAtTime, String jwtId, SignatureAlgorithm algorithm, Key secretKey) {
|
||
|
JwtBuilder builder = Jwts.builder()
|
||
|
.setIssuer(issuer)
|
||
|
.setSubject(subject)
|
||
|
.setAudience(audience)
|
||
|
.setExpiration(expiration)
|
||
|
.setNotBefore(notBeforeTime)
|
||
|
.setIssuedAt(issuerAtTime)
|
||
|
.setId(jwtId)
|
||
|
.signWith(algorithm, secretKey);
|
||
|
return builder.compact();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 创建默认的token,用不超时
|
||
|
*
|
||
|
* @param subject 主题
|
||
|
* @return token
|
||
|
*/
|
||
|
public static String createDefaultJWT(String subject) {
|
||
|
JwtBuilder builder = Jwts.builder()
|
||
|
.setIssuer(ISSUER)
|
||
|
.setIssuedAt(new Date())
|
||
|
.setSubject(subject)
|
||
|
.setId(JWT_ID)
|
||
|
.signWith(DEFAULT_ALGORITHM, getKeyBytes());
|
||
|
return builder.compact();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 创建默认的token
|
||
|
*
|
||
|
* @param subject 主题
|
||
|
* @param description 描述
|
||
|
* @return token
|
||
|
*/
|
||
|
public static String createDefaultJWT(String subject, String description) {
|
||
|
JwtBuilder builder = Jwts.builder()
|
||
|
.setIssuer(ISSUER)
|
||
|
.setIssuedAt(new Date())
|
||
|
.setSubject(subject)
|
||
|
.setDescription(description)
|
||
|
.setId(JWT_ID)
|
||
|
.signWith(DEFAULT_ALGORITHM, getKeyBytes());
|
||
|
return builder.compact();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 创建默认token
|
||
|
*
|
||
|
* @param subject 主题
|
||
|
* @param description 描述
|
||
|
* @param timeout 超时时长
|
||
|
* @return token
|
||
|
*/
|
||
|
public static String createDefaultJWT(String subject, String description, long timeout) {
|
||
|
Date currentTime = new Date();
|
||
|
Date timeoutTime = new Date(currentTime.getTime() + timeout);
|
||
|
JwtBuilder builder = Jwts.builder()
|
||
|
.setIssuer(ISSUER)
|
||
|
.setIssuedAt(currentTime)
|
||
|
.setExpiration(timeoutTime)
|
||
|
.setSubject(subject)
|
||
|
.setDescription(description)
|
||
|
.setId(JWT_ID)
|
||
|
.signWith(DEFAULT_ALGORITHM, getKeyBytes());
|
||
|
return builder.compact();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 创建有超时时限的token
|
||
|
*
|
||
|
* @param subject 主题
|
||
|
* @param timeout 超时时长
|
||
|
* @return token
|
||
|
*/
|
||
|
public static String createDefaultJWT(String subject, long timeout) {
|
||
|
Date currentTime = new Date();
|
||
|
Date timeoutTime = new Date(currentTime.getTime() + timeout);
|
||
|
JwtBuilder builder = Jwts.builder()
|
||
|
.setIssuer(ISSUER)
|
||
|
.setIssuedAt(currentTime)
|
||
|
.setExpiration(timeoutTime)
|
||
|
.setSubject(subject)
|
||
|
.setId(JWT_ID)
|
||
|
.signWith(DEFAULT_ALGORITHM, getKeyBytes());
|
||
|
return builder.compact();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 解析token
|
||
|
*
|
||
|
* @param jwt token字符串
|
||
|
* @return 签名通过之后的结果集
|
||
|
* @throws SignatureException 签名错误异常
|
||
|
*/
|
||
|
public static Map<String, Object> parseJWT(String jwt) {
|
||
|
try {
|
||
|
return Jwts.parser().setSigningKey(getKeyBytes()).parseClaimsJws(jwt).getBody();
|
||
|
} catch (SignatureException e) {
|
||
|
LogKit.warn(e.getMessage());
|
||
|
}
|
||
|
return new DefaultClaims();
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* 根据自定义的key,创建token
|
||
|
*
|
||
|
* @param signatureKey 秘钥
|
||
|
* @param claims token携带的信息
|
||
|
* @return token
|
||
|
*/
|
||
|
public static String createVariedJWT(String signatureKey, Map<String, Object> claims) {
|
||
|
JwtBuilder builder = Jwts.builder()
|
||
|
.setIssuer(ISSUER)
|
||
|
.setIssuedAt(new Date())
|
||
|
.setClaims(claims)
|
||
|
.setId(JWT_ID)
|
||
|
.signWith(DEFAULT_ALGORITHM, signatureKey);
|
||
|
return builder.compact();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 根据自定义的key,创建token
|
||
|
*
|
||
|
* @param signatureKey 秘钥
|
||
|
* @param timeout 有效期
|
||
|
* @param claims token携带的信息
|
||
|
* @return token
|
||
|
*/
|
||
|
public static String createVariedJWT(String signatureKey, long timeout, Map<String, Object> claims) {
|
||
|
Date currentTime = new Date();
|
||
|
Date timeoutTime = new Date(currentTime.getTime() + timeout);
|
||
|
JwtBuilder builder = Jwts.builder()
|
||
|
.setIssuer(ISSUER)
|
||
|
.setIssuedAt(new Date())
|
||
|
.setExpiration(timeoutTime)
|
||
|
.setClaims(claims)
|
||
|
.setId(JWT_ID)
|
||
|
.signWith(DEFAULT_ALGORITHM, signatureKey);
|
||
|
return builder.compact();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 解析token, 先对key进行utf-8解码
|
||
|
*
|
||
|
* @param jwt token字符串
|
||
|
* @param signatureKey 秘钥
|
||
|
* @return 签名通过之后的结果集
|
||
|
* @throws SignatureException 签名错误异常
|
||
|
*/
|
||
|
public static Map<String, Object> parseJWT(String jwt, String signatureKey) {
|
||
|
try {
|
||
|
return Jwts.parser().setSigningKey(signatureKey).parseClaimsJws(jwt).getBody();
|
||
|
} catch (SignatureException e) {
|
||
|
LogKit.warn(e.getMessage());
|
||
|
}
|
||
|
return new DefaultClaims();
|
||
|
}
|
||
|
|
||
|
private static byte[] getKeyBytes() {
|
||
|
try {
|
||
|
return SecurityToolbox.base642Byte(KeySecretSeedConfig.getInstance().getTrustSeed());
|
||
|
} catch (IOException e) {
|
||
|
LogKit.error("key secret seed base64 decode error");
|
||
|
}
|
||
|
return new byte[0];
|
||
|
}
|
||
|
}
|