发表于: 2021-12-12 21:32:06

0 944


JWT 是什么

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。


JWT 有什么用

JWT最常见的场景就是授权认证,一旦用户登陆,后续没个请求都将保护JWT ,系统每次处理用户请求之前都要浸洗JWT安全效验,通过之后再进行处理


JWT 主要由3部分组成

Header,payload,signature 

header

  • 声明类型,这里是jwt
  • 声明加密的算法 通常直接使用 HMAC SHA256

Payload

载荷就是存放有效信息的地方。

  • 标准中注册的声明
  • 公共的声明
  • 私有的声明

signature

jwt的第三部分是一个签证信息,这个签证信息由三部分组成:

  • header (base64后的)
  • payload (base64后的)
  • secret


使用JWT  在pom.xml添加依赖  

!--   java-jwt-->
   <dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.18.2</version>
</dependency>


创建工具类


public class JwtUtil {
//密钥 (salt盐)
   private static final String KEY = "tiles";
/*
   * 存入用户ID
   * 用户最后登陆时间
   * */
   public static String creatJwtName(String name) {
// 过期时间 7天
       Calendar calendar=Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR,7);

JWTCreator.Builder builder = JWT.create();
//       Claim声明
        builder.withClaim("name", name)
.withClaim("lastLoginTime", System.currentTimeMillis())
.withExpiresAt(calendar.getTime());
String token = builder.sign(Algorithm.HMAC256(KEY));
System.out.println(token);
return token;
}
/*
   * 存入User对象
   * */
   public  static  String creatJwtUser(TilesUser tilesUser){
// 过期时间
       Calendar calendar=Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR,7);

JWTCreator.Builder builder = JWT.create();
//       Claim声明
       builder.withClaim("UserInfo", JSONObject.toJSONString(tilesUser))
.withExpiresAt(calendar.getTime());
String token = builder.sign(Algorithm.HMAC256(KEY));
return token;
}
/*
       * 验证
       * */
   public static DecodedJWT verify(String verifyToken) {
DecodedJWT verify=null;
try {
verify=JWT.require(Algorithm.HMAC256(KEY)).build().verify(verifyToken);
}catch (SignatureVerificationException e){
e.printStackTrace();
System.out.println("签名不一致");
}catch (TokenExpiredException e){
e.printStackTrace();
System.out.println("令牌过期");
}catch (AlgorithmMismatchException e){
e.printStackTrace();
System.out.println("签名算法不匹配");
}catch (InvalidClaimException e){
e.printStackTrace();
System.out.println("payload不可用");
}catch (Exception e){
e.printStackTrace();
System.out.println("效验失败");
}
return verify;
}
/*
   *
   * 验证通过再解析
   * 解析为Uuser对象
   * */
   public static TilesUser parse(DecodedJWT decodedJWT){
Claim claim= decodedJWT.getClaim("UserInfo");
if (claim!=null){
String userString = claim.asString();
TilesUser tilesUser = JSON.parseObject(userString, TilesUser.class);
return tilesUser;
}
return null;
}

/*
   * 用户验证以后再解析
   * 解析出name
   * */
   public static String deJwtName(DecodedJWT decodedJWT){
Claim claim = decodedJWT.getClaim("name");
if (claim!=null){
String name = claim.asString();
return name;
}
return null;
}

}

测试工具类

public class CreatJwtTest {
private String key = "tiles";
@Test
   public void main() {
String token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsYXN0TG9naW5UaW1lIjoxNjM5Mjc5MDYxNjk2LCJuYW1lIjoi6YKT56eR6I2jIiwiZXhwIjoxNjM5MjgyNjYxLCJ1dWlkIjoiNWVmMjZjOTYtOWU3YS00Y2NjLWI3NWMtYWZiMTg5NGZhNzI4In0.7qCtXC2MKj0M71ihGWRkKhPbhVT8Xr6a3tutgAJ_eII";
DecodedJWT verify= JWT.require(Algorithm.HMAC256(key)).build().verify(token);
System.out.println(verify);
if (verify!=null){
System.out.println(verify.getClaim("name"));
long lastLoginTime= verify.getClaim("lastLoginTime").asLong();

Date date = new Date(lastLoginTime);
System.out.println(lastLoginTime);
System.out.println(date);
}
System.out.println(JwtUtil.verify(token));
if (JwtUtil.verify(token)!=null){
System.out.println(verify.getClaim("name"));
long lastLoginTime= verify.getClaim("lastLoginTime").asLong();

Date date = new Date(lastLoginTime);
}
}

//测试jwt存入name
   @Test
   public void Testjwt(){
String token = JwtUtil.creatJwtName("dengkerong");
System.out.println(token);
}
//测试解析出name
   @Test
   public void DeJwt(){
String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsYXN0TG9naW5UaW1lIjoxNjM5MjgyODgxODc1LCJuYW1lIjoiZGVuZ2tlcm9uZyIsImV4cCI6MTYzOTg4NzY4MX0.aT1RSciDYNLbPmCmKBTuQCUktc-zNj9fhCf4NP9y85c";

DecodedJWT verify = JwtUtil.verify(token);
if (verify!=null){
String name = JwtUtil.deJwtName(verify);
System.out.println(name);
}
}
//测试存入User对象
   @Test
   public void objectTestjwt(){
TilesUser tilesUser = new TilesUser();
tilesUser.setTilesUsername("邓科荣");
tilesUser.setTilesPassword("123456");
String token= JwtUtil.creatJwtUser(tilesUser);
System.out.println(token);
}

/*测试解析User*/
       @Test
       public void parse() {
String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJVc2VySW5mbyI6IntcInRpbGVzUGFzc3dvcmRcIjpcIjEyMzQ1NlwiLFwidGlsZXNVc2VybmFtZVwiOlwi6YKT56eR6I2jXCJ9IiwiZXhwIjoxNjM5OTE0MDc3fQ.RfiayYIG3egXSZIpGniaai1ellMv7JMCJHFOu46f4j8";
DecodedJWT verify = JwtUtil.verify(token);
System.out.println(JwtUtil.parse(verify));

TilesUser tilesUser = JwtUtil.parse(verify);
System.out.println(tilesUser.getTilesUsername());
System.out.println(tilesUser);
}
}


优点

  • 因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。
  • 因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。
  • 便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。
  • 它不需要在服务端保存会话信息, 所以它易于应用的扩展

安全相关

  • 不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。
  • 保护好secret私钥,该私钥非常重要。
  • 如果可以,请使用https协议




返回列表 返回列表
评论

    分享到