什么是JWT
json web token(JWT)是為了網(wǎng)絡應用環(huán)境間傳遞聲明而執(zhí)行的一種基于JSON的開發(fā)標準(RFC 7519)双妨,該token被設計為緊湊且安全的红柱,特別適用于分布式站點的單點登陸(SSO)場景。JWT的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便于從資源服務器獲取資源,也可以增加一些額外的其它業(yè)務邏輯所必須的聲明信息,該token也可直接被用于認證踊兜,也可被加密。
準備
新建一個maven工程棵里,并創(chuàng)建一個模塊(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>
使用流程
創(chuàng)建公鑰密鑰
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";
//創(chuàng)建公鑰私鑰
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添加存放的信息;
- 可以自己創(chuàng)建claims殿怜;
Map<String, Object> claims = new HashMap();
claims.put("username", loginName);
claims.put("userid", id);
Jwts.builder().setClaims(claims)
公鑰解析token
自定義SigningKeyResolver
根據(jù)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);
}