Browse Source

token生产工具类

master
richie 5 years ago
parent
commit
eb5b0d3b4c
  1. 213
      src/main/java/com/fanruan/api/security/JwtKit.java
  2. 77
      src/test/java/com/fanruan/api/security/JwtKitTest.java

213
src/main/java/com/fanruan/api/security/JwtKit.java

@ -0,0 +1,213 @@
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];
}
}

77
src/test/java/com/fanruan/api/security/JwtKitTest.java

@ -0,0 +1,77 @@
package com.fanruan.api.security;
import com.fanruan.api.Prepare;
import com.fr.cert.token.JwtBuilder;
import com.fr.cert.token.Jwts;
import com.fr.cert.token.SignatureAlgorithm;
import com.fr.security.SecurityToolbox;
import com.fr.stable.CodeUtils;
import org.junit.Assert;
import org.junit.Test;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-09-03
*/
public class JwtKitTest extends Prepare {
@Test
public void testCreateDefaultJWT() throws Exception {
String tokenCN = JwtKit.createDefaultJWT("你好,我是中国人");
Map<String, Object> claims = JwtKit.parseJWT(tokenCN);
Assert.assertEquals("你好,我是中国人", CodeUtils.cjkDecode(String.valueOf(claims.get("sub"))));
String tokenEN = JwtKit.createDefaultJWT("Hello, world");
Map<String, Object> claims2 = JwtKit.parseJWT(tokenEN);
Assert.assertEquals("Hello, world", CodeUtils.cjkDecode(String.valueOf(claims2.get("sub"))));
}
@Test
public void testClaims() throws Exception {
String token = JwtKit.createDefaultJWT("千万", "我是千万的爹");
Map<String, Object> claims2 = JwtKit.parseJWT(token);
String text = CodeUtils.cjkDecode(String.valueOf(claims2.get("description")));
Assert.assertEquals("我是千万的爹", text);
}
@Test
public void test1() throws UnsupportedEncodingException {
String token = createToken().compact();
Assert.assertEquals(Jwts.parser().setSigningKey("abc=啊").parseClaimsJws(token).getBody().getSubject(), "hello.cpt");
token = createToken().signWithBase64SecretKey(SignatureAlgorithm.HS256, SecurityToolbox.byte2Base64("abc=啊".getBytes())).compact();
Assert.assertEquals(Jwts.parser()
.setBase64SigningKey(SecurityToolbox.byte2Base64("abc=啊".getBytes()))
.parseClaimsJws(token).getBody().getSubject(), "hello.cpt");
token = createToken()
.signWith(SignatureAlgorithm.HS256, "abc=啊".getBytes("GBK"))
.compact();
Assert.assertEquals("hello.cpt", Jwts.parser().setSigningKey("abc=啊".getBytes("GBK")).parseClaimsJws(token).getBody().getSubject());
}
private JwtBuilder createToken() {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
Calendar calendar = Calendar.getInstance();
calendar.set(2019, Calendar.FEBRUARY, 20, 18, 0, 0);
Date currentTime = calendar.getTime();
calendar.set(2029, Calendar.FEBRUARY, 20, 18, 0, 0);
Date expirationTime = calendar.getTime();
return Jwts.builder()
.setHeaderParam("typ", "JWT")
.setIssuer("fanruan")
.setSubject("hello.cpt")
.setExpiration(expirationTime)
.setIssuedAt(currentTime)
.setId("01")
.signWith(signatureAlgorithm, "abc=啊");
}
}
Loading…
Cancel
Save