2019-02-15 · Develop

JWT 简明教程

什么是 JWT

JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,本文介绍它的原理和用法。

应用程序或者客户端向服务器请求授权,授权服务器向客户端返回一个 JWT。之后将 JWT 放入到请求里(通常放在 HTTP 的 Authorization 头里)。服务器接收请求后,验证 JWT 并执行对应的逻辑。为了防止用户的信息被篡改,服务器在生成这个对象的时候,会加上签名。JWT 的大体结构如下

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

JWT 结构

JWT 有三部分组成,中间用(.)进行分割,JWT 是没有换行的。三个部分以次为Header(头部)Payload(负载)Signature(签名)。就如 JWT 网站 的示例一样

jwt-hs256

Header 部分是将一个 Json 对象进行 Base64URL 算法之后的字符串。其中 alg 表示签名的算法(algorithm)为 HMAC SHA256(写成 HS256)。 typ 表示 token (令牌)的类型为 JWT

Payload

Payload 部分和 Header 一样是将 JSON 对象进行 Base64URL 转换。其中 JWT 规格的官方字段含义如下

除了官方的字段外,也是可以进行自定义字段的。

Signature

Signature 部分是对前两部分的签名,防止数据篡改。HS256 的算法如上图所示的

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)

jjwt 实现

首先引入依赖

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.7.0</version>
</dependency>

生成 JWT Token

// 生成 JWT Token
public static String generateToken(String payload) {
    Date now = new Date();
    Date expire = new Date(now.getTime() + 5 * 60 * 1000);
    return Jwts.builder()
            .setHeaderParam("typ", "JWT")
            .setSubject(payload)
            .setIssuedAt(now)
            .setExpiration(expire)
            .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
            .compact();
}

此处生成一个过期时间为 5 分钟的 Token

校验 Token

下面对是否合法和是否过期进行校验

// 解析 Token
private static Claims parseToken(String token) {
    try {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
    } catch (Exception e) {
        return null;
    }
}

// 校验 Token 是否合法
public static boolean isTokenValid(String token) {
    return parseToken(token) != null;
}

// 校验 Token 是否过期/失效
public static boolean isTokenExpired(String token) {
    Claims claims = parseToken(token);
    return claims != null && claims.getExpiration().before(new Date());
}

更新 Token

对于 Token 应该在用户每次操作后都更新其过期时间,俗称喂狗

// 更新 Token 的过期时间
public static String updateToken(String token) {
    Claims claims = parseToken(token);
    return claims == null ? null : generateToken(claims.getSubject());
}

JWT 的特点


参考资料