JWT是什么
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
JSON Web Token的结构
JSON Web Token由三部分组成,它们之间用圆点(.)连接。这三部分分别是:
HeaderPayloadSignatureJWT与Session的差异
相同点是,它们都是存储用户信息;然而,Session是在服务器端的,而JWT是在客户端的。
Session方式存储用户信息的最大问题在于要占用大量服务器内存,增加服务器的开销。
而JWT方式将用户状态分散到了客户端中,可以明显减轻服务端的内存压力。
Session的状态是存储在服务器端,客户端只有session id;而Token的状态是存储在客户端。
JWT代码案例
依赖:
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency> import io.jsonwebtoken.*; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.Date; import java.util.Map; import java.util.UUID; @Component public class JwtUtil { /** * 生成签名的时候使用的秘钥secret,它就是你服务端的私钥,在任何场景都不应该流露出去 */ @Value("${jwt.key}") private String defaultJwtKey; /** * 生成签发人 */ @Value("${jwt.subject}") private String jwtSubject; /** * jwt有效时间,单位:毫秒 */ @Value("${jwt.ttlMillis}") private Long defaultTtlMillis; /** * @param claims body内容 * @return */ public String generateJWT(Map<String, Object> claims) { return this.generateJWT(claims, defaultTtlMillis); } /** * * @param claims body内容 * @param ttlMillis jwt过期时间 * @return */ public String generateJWT(Map<String, Object> claims, long ttlMillis) { return this.generateJWT(claims, defaultJwtKey, defaultTtlMillis); } /** * * @param claims body内容 * @param jwtKey jwt秘钥 * @return */ public String generateJWT(Map<String, Object> claims, String jwtKey) { return this.generateJWT(claims, jwtKey, defaultTtlMillis); } /** * @param claims body内容 * @param jwtKey jwt秘钥 * @param ttlMillis jwt过期时间 * @return */ public String generateJWT(Map<String, Object> claims, String jwtKey, long ttlMillis) { //指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。 SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; //生成JWT的时间 long nowMillis = System.currentTimeMillis(); Date now = new Date(nowMillis); //下面就是在为payload添加各种标准声明和私有声明了 //这里其实就是new一个JwtBuilder,设置jwt的body JwtBuilder builder = Jwts.builder() //如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的 .setClaims(claims) //设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。 .setId(UUID.randomUUID().toString()) //iat: jwt的签发时间 .setIssuedAt(now) //代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可以存放什么userid,roldid之类的,作为什么用户的唯一标志。 .setSubject(jwtSubject) //设置签名使用的签名算法和签名使用的秘钥 .signWith(signatureAlgorithm, jwtKey); if (ttlMillis >= 0) { long expMillis = nowMillis + ttlMillis; Date exp = new Date(expMillis); //设置过期时间 builder.setExpiration(exp); } return builder.compact(); } /** * * @param token 加密后的token * @param jwtKey jwt秘钥 * @return */ public Claims parseJWT(String token, String jwtKey) { Jws<Claims> jws = Jwts.parser() //设置签名的秘钥 .setSigningKey(jwtKey) //设置需要解析的jwt .parseClaimsJws(token); return jws.getBody(); } /** * * @param token 加密后的token * @return */ public Claims parseJWT(String token) { return parseJWT(token, defaultJwtKey); } }
