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 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 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 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 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]; } }