JWT(JSON Web Token )详解及实例

2024-05-13 1306阅读

温馨提示:这篇文章已超过370天没有更新,请注意相关的内容是否还可用!

目录

JWT(JSON Web Token )详解及实例
(图片来源网络,侵删)

一、什么是 JWT ?

二、什么时候使用 JWT ?

三、JWT 格式

1、Header

2、Payload

3、Signature

4、 JWT实现:


官网

  • 官网 JSON Web Tokens - jwt.io
  • RFC 7519文档 RFC 7519: JSON Web Token (JWT)

    一、什么是 JWT ?

    JSON Web Token(JWT)是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间作为JSON对象安全地传输信息。

    JWT可以使用密码(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。

    加签后的token 能够使用 JWT 里的算法验证 json 的完整性.

    二、什么时候使用 JWT ?

    1. 授权
    2. 信息交换
    3. 使用方式:服务端根据规范生成一个令牌(token),并且发放给客户端(保存在客户端)。此时客户端请求服务端的时候就可以携带者令牌,以令牌来证明自己的身份信息。
    4. 前端在每次请求时将JWT放入HTTP Header中的Authorization位。(解决XSS和XSRF问题)

    JWT优势

        简洁:可以通过URL、POST参数或者在HTTP Header发送,因为数据量小,传输速度也很快

        自包含:负载中包含了所有用户所需要的信息,避免了多次查询数据库

        因为Token是以JSON加密的形式保存在客户端的,所以JWT是跨语言的,原则上任何web形式       都支持

        不需要在服务端保存会话信息,特别适合用于分布式微服务。

        更适合用于移动端:当客户端是非浏览器平台时,cookie是不被支持的,此时使用token认证方       式会简单很多

         单点登录友好:由于cookie无法跨域,难以实现单点登录。但是,使用token进行认证的话,            token可以被保存在客户端的任意位置的内存中,不一定是cookie,所以不依赖cookie,不会          存在这些问题

     

    三、JWT 格式

    使用逗号分隔的三部分 :

    • Header
    • Payload
    • Signature

      token 格式:xxxxx.yyyyy.zzzzz

      Header 通常由 token 类型和签名算法名两部分组成.是token的第1部分

      例如:

      {
      "alg": "HS256", // 签名算法
      "typ": "JWT" // token类型
      }

      然后, 这个JSON 使用 Base64Url 编码后放到 JWT 的第1部分.

      2、Payload

      Payload 是token的第2部分.包含了一些声明(claims).声明的名字必须是唯一的.

      claims 是包含了 用户数据和其他数据的陈述,

      有三种类型的声明:

      1. Registered Claim Name

        预定义好的一些声明(如果有需要就使用,没需要可不使用):

      • "iss"
      • "sub"
      • "aud"
      • "exp"
      • "nbf"
      • "iat"
      • "jti"

        更多参见 JSON Web Token (JWT)

        1. Public Claim Names

          公共的声明,可以预先定义在 IANA JSON Web Token Registry 中,或者定义在1个能解决名字冲突的地方.

        2. Private Claim Names

          双方共享数据使用的私有名字.既不在 Registered Claim Name 也不在 Public Claim Names 中.

        payload 示例

        {
        "sub": "1234567890",
        "name": "John Doe",
        "admin": true
        }

        JSON 

        然后, 这个JSON 使用 Base64Url 编码后放到 JWT 的第2部分.

        3、Signature

        拿到编码后的 header 和 编码后的 payload 使用 密码进行签名.

        使用 HMAC SHA256 加签示例:

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

        Signature需要使用编码后的header和payload以及我们提供的一个秘钥,然后使用header中指定的签名算法进行签名,签名的作用是保证JWT没有被篡改过

        HMACSHA256(base64UrlEncode(header)+“.”+base64UrlEncode(payload),secret)

        实际上是对头部信息和负载内容进行签名,防止内容被篡改,如果有人对头部以及负载内容解码后进行修改,再进行编码,最后加上之前的签名组合形成新的JWT的话,那么服务器端会判断出新的头部和负载形成的签名和JWT上附带的签名是不一样的。如果要对新的头部和负载进行签名,由于不知道服务器加密时使用的秘钥,得出来的结果也是不一样的

        注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。

        4、 JWT实现:

          1、依赖引入

                
                    io.jsonwebtoken
                    jjwt
                    ${jwt-jsonwebtoken.version}
                
                
                    com.alibaba
                    fastjson
                    RELEASE
                

        2、生成Token 

        // 签名密钥
         private static final String SECRET = "!Doker$";
        public String createToken(Map claims, String subject) {
                final Date createdDate = clock.now();
                final Date expirationDate = calculateExpirationDate(createdDate);
                return Jwts.builder()
                        .setClaims(claims)
                        .setSubject(subject)
                        .setIssuedAt(createdDate)
                        .setExpiration(expirationDate)
                        .signWith(SignatureAlgorithm.HS512, Algorithm.HMAC256(SECRET))
                        .compact();
            }
            private Date calculateExpirationDate(Date createdDate) {
                return new Date(createdDate.getTime() + expiration * 1000);
            }

        3、刷新Token 

        public String RefreshToken(String token) {
                final Date createdDate = clock.now();
                final Date expirationDate = calculateExpirationDate(createdDate);
                final Claims claims = getAllClaimsFromToken(token);
                claims.setIssuedAt(createdDate);
                claims.setExpiration(expirationDate);
                return Jwts.builder()
                        .setClaims(claims)
                        .signWith(SignatureAlgorithm.HS512, Secret)
                        .compact();
            }

        4、token发送给前端

        传入当前用户的功能与用户信息,登录名生成token,写入response的返回头中,前端获取后保存在前端的本地缓存中,后续前端请求要把token放在头header里。

        //登录成功之后
        List functs=(List) authResult.getAuthorities();
        //当前功能列表
        String loginName=authResult.getName();//登录名
        Users obj=(Users)authResult.getPrincipal();//用户信息
        String token=JwtUtil.createToken(loginName,functs,obj);
        //生成token  TOKEN_HEADER= Authorization TOKEN_PREFIX=Bearer token值
        response.setHeader(JwtUtil.TOKEN_HEADER,JwtUtil.TOKEN_PREFIX+token);
        response.setContentType("application/json;charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK); //个人编写的视图对象
        DTO dto=new DTO();
        dto.setCode("000000");
        dto.setMessage("认证通过");
        PrintWriter pw=response.getWriter();
        pw.write(JsonUtil.set(dto));//写入json
        pw.flush();//强制刷新
        pw.close();//关闭流

        5、验证用户请求携带token

        String header = request.getHeader(JwtUtil.TOKEN_HEADER);
         if (null == header || !header.toLowerCase().startsWith(JwtUtil.TOKEN_PREFIX)) { 
          // 如果头部 Authorization 未设置或者不是 basic 认证头部,则当前 
          // 请求不是该过滤器关注的对象,直接放行,继续filter chain 的执行
           chain.doFilter(request, response);
           return;
        } 
        try {
          String token = header.replace(JwtUtil.TOKEN_PREFIX, ""); 
          // 验证token是否过期
          if (JwtUtil.isExpiration(token)) { 
              throw new javax.security.sasl.AuthenticationException("token 验证不通过");
        } 
        //檢查token是否能解析
        Users user = (Users) JwtUtil.getUser(token); 
        if (null == user) { 
            throw new javax.security.sasl.AuthenticationException("token 验证不通过");
        } 
        //验证成功
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]