JWT是JSON Web Token的简称,是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准,常用于登录认证,客户端请求时通过头部携带服务端生成的token令牌来验证身份。
JWT令牌由头部(Header)、负载(Payload)、签名(Signature)三部分组成,每部分通过.符号连接,形式为
Header.Payload.Signature
JWT的头部是一个JSON对象,描述JWT的元数据类型,通常有两个字段:alg和typ, alg表示JWT的签名算法,默认是HS256算法,typ属性表示令牌的token类型,为JWT令牌时typ的值为JWT,
头部的常见形式如下:
{
“alg”:“HS256”,
“alg”:“JWT”
}
负载也是一个JSON对象,用来存放实际传输的数据,规定7个官方的字段如下:
- iss (issuer):签发人
- exp (expiration time):过期时间
- sub (subject):主题
- aud (audience):受众
- nbf (Not Before):生效时间
- iat (Issued At):签发时间
- jti (JWT ID):编号
除了7个官方字段外,我们还可以自定义要传输的字段,比如:
{
“account”: “12334556”,
“name”:“xiaoming”
}
由于JWT默认对传输数据不加密,所以不要通过JWT传输敏感信息。
JWT采用签名的方式来验证传输的数据是否被篡改。通过指定一个签名密钥,对前两部分头部和负载通过Base64URL算法编码后的内容进行加密,生成签名部分的数据,头部、负载、签名三部分通过.符号进行连接,形成一个JWT的token令牌返回给客户端。如果数据被篡改,通过原来签名组成新的token令牌,服务器端通过被篡改数据生成的签名与原来的不一样,携带纂改数据的请求无发通过验证;如果替换掉原来的签名,由于不知道服务器的加密秘钥,也无法通过认证。以HS256加密算法为例,生成签名的公式如下:
HS256(BaseURLEncode(Header) + “.” + BaseURLEncode(Payload), secret)
引入JWT的依赖
io.jsonwebtoken jjwt 0.9.1
创建生成token和验证token的工具类JWTUtils, 代码如下:
public class JWTUtils {// JWT加密秘钥,自定义private static final String jwtToken = "13suwbxsjxn!@#$%^&*!@$$";public static String createToken(Long userId) {// 自定义负载Map clains = new HashMap<>();clains.put("userId", userId);// 生成JWT创建对象,自行设置需要的官方负载字段JwtBuilder jwtBuilder = Jwts.builder().signWith(SignatureAlgorithm.HS256, jwtToken).setClaims(clains).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000));// 生成tokenString token = jwtBuilder.compact();return token;}public static Map checkToken(String token) {try {// 验证token,并返回负载中的数据Jwt parse = Jwts.parser().setSigningKey(jwtToken).parse(token);return (Map) parse.getBody();} catch (Exception e) {e.printStackTrace();}return null;}
}
简单写个验证程序如下:
public static void main(String[] args) {String token = createToken(123456776543123456L);System.out.println("================生成的token==============" );System.out.println(token);System.out.println("================验证token================");System.out.println(checkToken(token));}
运行结果如图片所示: