1.JWT应用场景
JWT官网:点此进入
JWT一般用于网站的授权认证的过程
前端在每次请求时将JWT放在请求连接header中的Authorization位
后端会检查JWT的合法性
- 签名是否正确
- 检查token是否过期
2.JWT的结构
JWT通过三部分组成:
- 1.header(标头) :
token的类型(即JWT)
和所使用的的签名算法
,如:HMAC, SHA256, RSA,然后使用Base64对标头进行编码形成JWT的第一部分。 - 2.payload(有效负载):有效负载包含用户的数据声明,同样会使用Base64对该部分进行编码形成JWT第二部分。
- 3.signature(签名):签名使用的是经过编码后的header和payload以及后端提供的一个秘钥,然后使用header中的签名算法进行签名。签名的目的是保证JWT没有被篡改。
eg: HMACSHA256(Base64UrlEncode(header) + “.” + Base64UrlEncode(payload), secret);
JWT最后由三者通过.
号连接组成,其表示形式header.payload.signature
Note: Base64是一种编码,是可逆的; 解密不可逆
如果有人对头部或者有效负载部分的数据解码后进行修改,然后再对修改后的数据进行编码拼上之前的签名形成的一个新的JWT,此时服务器会对修改后的数据重新签名,形成新的签名和新的JWT所挂载的签名是不一致的;如果修改签名的话,同样行不通。
3.JWT的实践
3.1添加依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
3.2代码展示
public class TestJWT {
public static final String salt = "www.baidu.com";
public static void main(String[] args) {
String token = createToken();
DecodedJWT verify = createVerifierObject().verify(token);
String userId = verify.getClaim("userId").asString();
String userName = verify.getClaim("userName").asString();
String age = verify.getClaim("age").asString();
/**
*result:
* userId:34343
* userName:zhangsan
* age:null
*/
System.out.println("userId:" + userId);
System.out.println("userName:" + userName);
System.out.println("age:" + age);
/**
* age:33
*/
int ages = verify.getClaim("age").asInt();
System.out.println("age:" + ages);
}
public static String createToken() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 300);
String token = JWT.create()
.withClaim("userName", "zhangsan")
.withClaim("userId", "34343")
.withClaim("age", 33)
.withExpiresAt(calendar.getTime()).sign(Algorithm.HMAC256(salt));
return token;
}
public static JWTVerifier createVerifierObject() {
return JWT.require(Algorithm.HMAC256(salt)).build();
}
}
3.2代码解释
代码中的salt一般是系统的配置中提供的,该字符串千万不要暴露出去,一旦暴露出去就会导致系统的不安全。
一般情况下接口均会做JWT的安全权限校验,因此可以在项目中使用拦截器的方式实现。如果是在分布式的项目中则得在网关中做处理。