码迷,mamicode.com
首页 > 其他好文 > 详细

JWT学习小结

时间:2018-04-02 20:02:24      阅读:425      评论:0      收藏:0      [点我收藏+]

标签:tde   blog   也会   base64   格式   cti   die   public   cat   

JWT的定义

JWT(Json Web Token)是一个轻巧的开放标准(RFC 7519),它定义了一种安全可靠的传输信息的方式,所传输的信息是一个‘小巧’和‘自包含’的JSON对象。作为一个标准,它没有具体的技术实现,不过现在大多数语言平台都按照其标准提供了具体的技术实现。我们在实际的使用过程中,只需要根据具体的技术平台,使用相应的实现库就可以。

使用场景

在实际使用中:JWT主要解决以下两个问题:

  1. 认证: 由于JWT本身‘小巧’和‘自包含’的特点,最常见的用法是通过它来完成基于token的身份认证,服务端在用户首次账号和密码登录成功之后会返回JWT,后续的请求都需要带有这个JWT来作为身份认证的标识。。

  2. 信息安全传输:JWT的组成部分包含有数字签名,这让它可以作为一种安全传输信息的方式。

在平台服务化越来越普遍的今天,JWT可以作为开放API的权限认证一种方法,在合法客户端访问开放API时需要先从服务端获取JWT,在随后的请求中则需要在请求中携带JWT,服务端在验证JWT的有效性后再提供相应的服务。

JWT的结构

JWT是一个字符串,由三部分组成,分别是头部(header),载荷(payload)和签名(signature)。

格式如下:
header.payload.signature

头部(header)

JWT的头部用于描述JWT最基本的信息,如类型和签名所用的算法, 可表示为下面的json结构:

{
    "typ":"JWT",
    "alg":"HS256"
}

在生成JWT的header过程中会对这个json字符串进行BASE64编码为

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

载荷(Payload)

Payload里面是Token的具体内容,里面是一些标准字段,你也可以添加一些自定义字段,标准字段如下

iss:Issuer,发行者
sub:Subject,主题
aud:Audience,观众
exp:Expiration time,过期时间
nbf:Not before
iat:Issued at,发行时间
jti:JWT ID

比如下面这个Payload,包含有标准字段iss发行人和exp过期时间,还有自定义字段name

{
    "iss":"org.zy",
    "exp":"148895645"
    "name": "zy",
}

在生成JWT的Payload过程中也会对这个json字符串进行BASE64编码为

eyJpc3MiOiJvcmcuenkiLCJuYW1lIjoienkiLCJleHAiOiIxNDg4OTU2NDUifQ

这个时候你可能有疑惑,通过BASE64编码等同于传输的都是明文,如何保证安全?下面我们一起看看第三部分签名(Signature)

签名(Singature)

这部分是把BASE64编码的Header和Payload按照Header.Payload格式进行加密,加密算法在Header中已经指明,加密的密钥secretKey通常存在服务端。

最终生成的JWT为:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJvcmcuenkiLCJuYW1lIjoienkiLCJleHAiOiIxNDg4OTU2NDUifQ.MrP_jnb8ujP6WgcrP5G79IC4ojvVsX-UvwCSaiubbL8

至此,JWT字符串已经生成。这个JWT字符串作为后续请求服务的token。客户端把此token存储起来,在后续向服务器请求服务时就需要带上token,服务端在收到后会先进行验证,验证成功后才提供相应的服务。

Java代码示例

jjwt是java对JWT的封装,我们直接采用jjwt提供的方法来进行JWT的相关操作。

maven dependency:

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

服务端生成JWT:

public String generateJwt(Map<String,Object> claims){
    String jwt = Jwts.builder().setHeaderParam("typ", "JWT").
            signWith(SignatureAlgorithm.HS256, SECRET_KEY)
            .setClaims(claims).compact();
    return jwt;
}

服务端验证JWT

public boolean isJwtValid(String jwt){
    try{
        Claims claims = Jwts.parser().setSigningKey(SECRET_KEY)
                .parseClaimsJws(jwt).getBody();
        
        String value = claims.get("name", String.class);
        if("zy".equals(value)){
            return true;
        }else{
            return false;
        }
    }catch(SignatureException | ExpiredJwtException e){
        e.printStackTrace();
        return false;
    }
}

main方法测试:

public static void main(String[] args) {
    JWTDemo jwtdemo = new JWTDemo();
    Map<String,Object> claimMap = new HashMap<String,Object>();
    claimMap.put("iss", "org.zy");
    claimMap.put("exp", "1522658513590");
    claimMap.put("name", "zy");
    String jwt = jwtdemo.generateJwt(claimMap);
    System.out.println("The generated jwt: " + jwt);
    System.out.println("the validation of jwt:" + jwtdemo.isJwtValid(jwt));
}

注意事项

  1. 不要往Payload中存放敏感信息,签名部分只是保证传输的数据不被篡改。
  2. 尽量给token一个有效期,当然这将涉及到采用何种方法来处理过期token和产生新token的。
  3. 采用HTTPS,不要采用不安全的HTTP中去传输token。

小结

广义上讲JWT是一个轻量级的标准,狭义上JWT则是一个常用于认证功能的token字符串。 JWT本身很容易,它提供了一种基于token的请求验证机制。但API安全整体是一个比较复杂的问题.

JWT学习小结

标签:tde   blog   也会   base64   格式   cti   die   public   cat   

原文地址:https://www.cnblogs.com/yzhu/p/8695751.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!