什么是JWT
json web token(JWT)是为了网络应用环境间传递声明而执行的一种基于JSON的开发标准(RFC 7519),该token被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
准备
新建一个maven工程,并创建一个模块(springboot工程),并在pom文件添加JWT的依赖
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jjwt.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>${jjwt.version}</version>
<scope>runtime</scope>
</dependency>
使用流程
创建公钥密钥
public int KEY_SIZE = 2048;
public String ALGORITHM = "RSA";
public long TTL_MILLIS_ACCESS = 30 * 60 * 1000L; //30分钟
public long TTL_MILLIS_REFRESH = 7 * 24 * 60 * 60 * 1000L; //一周
public String RSA_PUBLIC = "_rsa_public";
public String RSA_PRIVATE = "_rsa_private";
public String KEY_ID = "key_id";
public String TOKEN_TYPE = "token_type";
public String TOKEN_TYPE_ACCESS = "_access_token";
public String TOKEN_TYPE_REFRESH = "_refresh_token";
public String GENERATE_TYPE_LOGIN = "login";
public String GENERATE_TYPE_REFRESH_TOKEN = "refresh_token";
//创建公钥私钥
KeyPairGenerator keyPairGenerator = null;
try {
keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
keyPairGenerator.initialize(KEY_SIZE);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
将公钥存放至redis
//将公钥私钥存入redis
redisUtils.set(loginName + TOKEN_TYPE_ACCESS + RSA_PRIVATE, rsaPrivateKey, TTL_MILLIS_ACCESS);
redisUtils.set(loginName + TOKEN_TYPE_ACCESS + RSA_PUBLIC, rsaPublicKey, TTL_MILLIS_ACCESS);
token生成
//生成access token
String accessToken = Jwts.builder()
.signWith(rsaPrivateKey)
.setHeaderParam(KEY_ID, loginName + TOKEN_TYPE_ACCESS)
.setHeaderParam(TOKEN_TYPE, TOKEN_TYPE_ACCESS)
.setClaims(claims)
.setIssuer("lczy")
.setSubject("auth")
.setAudience(loginName)
.setExpiration(new Date(nowMillis + TTL_MILLIS_ACCESS)) //a java.util.Date
.setNotBefore(now) //a java.util.Date
.setIssuedAt(now) // for example, now
.setId(String.valueOf(UUID.randomUUID())) //just an example id
.compact();
- 可以在HeaderParam添加存放的信息;
- 可以自己创建claims;
Map<String, Object> claims = new HashMap();
claims.put("username", loginName);
claims.put("userid", id);
Jwts.builder().setClaims(claims)
公钥解析token
自定义SigningKeyResolver
根据header存放的redis key 从redis中获取相应的
public class MySigningKeyResolver extends SigningKeyResolverAdapter {
Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
RedisUtils redisUtils;
@Autowired
JwtUtils jwtUtils;
@Override
public Key resolveSigningKey(JwsHeader header, Claims claims) {
String keyid = (String) header.get(jwtUtils.KEY_ID);
logger.info("Jwt resolveSigningKey : " + keyid);
return (Key) redisUtils.get(keyid + jwtUtils.RSA_PUBLIC);
}
}
解析token
public Jws<Claims> parserToken(String token) throws Exception {
return Jwts.parser().setSigningKeyResolver(mySigningKeyResolver).parseClaimsJws(token);
}
网友评论