• JWT


    1. 简介

    JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。

    实际上就只规范如何产生一个加密的字符串 token,它就长这个样子

    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlzcyI6Imh0dHA6Ly8xMC4zLjE5Ljg2OjkwODAvYXBpL3NpZ25pbiIsImlhdCI6MTUyMTYxODc3MSwiZXhwIjoxNTIxNjMzMTcxLCJuYmYiOjE1MjE2MTg3NzEsImp0aSI6ImhjMHNQMFdXcnVHbmJ4SFMifQ.Yc9X6q0A1QRGoEXfzS63cbeICoZPB_7vWkRqBypdiiU
    

    2. token的组成

    上面的token由.分隔成三段,第一部分称为头部(header),第二部分们称为载荷(payload),第三部分是签证(signature)

    2.1 header

    jwt的头部承载两部分信息:

    • 声明类型,这里是jwt
    • 声明加密的算法 通常直接使用 HMAC SHA256
    {
      'typ': 'JWT',
      'alg': 'HS256'
    }
    

    将头部信息进行base64加密(可以对称解密),构成第一部分,暂且记做$header_str

    2.2 payload

    载荷负责存放有效信息,实际上包括标准声明和非标准声明

    1. 标准声明(建议并不强制使用)
    • iss: jwt签发者
    • sub: jwt所面向的用户
    • aud: 接收jwt的一方
    • exp: jwt的过期时间,这个过期时间必须要大于签发时间
    • nbf: 定义在什么时间之前,该jwt都是不可用的.
    • iat: jwt的签发时间
    • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
    1. 非标准部分可以写入用户的id等需要的信息
    {
        "iss": "test",
        "iat": 1441593502,
        "exp": 1441594722,
        "aud": "www.example.com",
        "user_id": 1,
    }
    

    将载荷信息进行base64机密,构成第二部分,暂且记做$payload_str

    2.3 signature

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

    • header (base64后的)
    • payload (base64后的)
    • secret
    1. 将加密后的第一部分和第二部分使用.连接形成字符串
    $header_payload_str = $header_str . '.' . $payload_str;
    
    1. 使用header中声明的加密方式加密,形成第三部分,记做$signature
    $signature = HMACSHA256($header_payload_str, 'secret');
    

    最后将上面加密后的三部分使用.连接,构成最终的token

    $token = $header_str . '.' . $payload_str . '.' . $signature;
    

    3. 使用

    用户进行登录操作,如果登录信息合法,服务端生成token字符串,响应中将token信息传递给客户端,客户端并将token信息存储在客户端,以后每次请求的时候带着token信息,服务端收到每次请求后都验证token是否存在并且合法有效,来确认用户是否登录

    一般是在请求头中加入,比如我在vue中axios拦截中每次请求带着token信息

    axios.interceptors.request.use(
        config => {
            let token = sessionStorage.getItem('token');
            if (token) {
                config.headers['Authorization'] = 'Bearer ' + token
            }
            return config
        },
        err => {
            return Promise.reject(err);
        }
    )
    

    4. 单点登录

    4.1 同一顶级域名下

    举个例子

    • www.taobao.com 服务器www
    • a.tabao.com 服务器a
    • b.tabao.com 服务器b

    不同的二级域名对应不同的服务器,如果使用服务器存储session的方式,就需要我们在多台服务器上同步session信息,但是使用jwt就没有这个问题,jwt_token已经记录了用户信息,并且已经存储在客户端,我们只需要将token信息存储在顶级域名下即可。

    比如

    Set-Cookie: jwt=lll.zzz.xxx; HttpOnly; max-age=980000; domain=.taobao.com
    

    注意domain必须设置为一个点加顶级域名,即.taobao.com。这样,taobao.com和*.taobao.com就都可以接受到这个Cookie,并获取JWT了

    4.2 跨域单点登录

    举个例子

    • www.taobao.com 服务器www
    • a.com 服务器a
    • b.com 服务器b

    提供两个解决方法

    1. 一个域名登录成功,在客户端针对其他每个站点在浏览器端设置cookie信息

    2. 借助单独的sso服务器,只需存储该sso服务器域名下的cookie信息,在这种模型下,针对任何站点的请求都将会先重定向到SSOsite去验证一个身份验证cookie是否存在。如果存在,则验证过的页面将会发送给浏览器。否则用户将会被重定向到登录页面。

    5. 关于token泄露

    token如果泄露,别人就可以通过token来进行非法操作,因为服务端只判定token是否合法,并不会验证使用者。

    泄露一般存在两个地方

    1.传输层

    token在传输层被拦截,传统的cookie存储的sessionId也有一样的问题,所以建议使用https协议,安全性更有保证。

    2.客户端

    如果cookie可以被窃取,token也没办法解决这个问题。拦截到cookie后,把cookie放在另一台电脑上也是可以使用的,这个跟token是一样的。

    6. 总结

    1. jwt是一个标准,可以跨语言使用。
    2. jwt构成简单,这用字节小,便于传输,不会因为每次请求头都带着token过于影响性能。
    3. 不需要在服务端保存会话信息,减轻服务器压力同时易于扩展。
    4. payload部分是对称解密,不应该存储敏感信息。
    5. 保护好私钥,否则别人可以伪造token
  • 相关阅读:
    java 数据类型:集合接口Collection之List~ArrayList:remove移除;replaceAll改变原有值;sort排序;迭代器listIterator();
    java 数据类型:集合接口Collection之常用ArrayList;lambda表达式遍历;iterator遍历;forEachRemaining遍历;增强for遍历;removeIf批量操作集合元素(Predicate);
    java 常用类库:格式化NumberFormat;SimpleDataFormat类(转换Data()对象);DateTimeFormatter 转换LocalDateTime时间对象
    java 常用类库:时间类LocalDate;LocalTime;LocalDateTime;Calendar 类;Date ;
    java 常用类库:BigInteger大整数;BigDecimal大小数(解决double精度损失);
    java 常用类库:Math:常用min、max;floor;ceil;random;
    1345. Jump Game IV
    1298. Maximum Candies You Can Get from Boxes
    1293. Shortest Path in a Grid with Obstacles Elimination
    1263. Minimum Moves to Move a Box to Their Target Location
  • 原文地址:https://www.cnblogs.com/redirect/p/10066665.html
Copyright © 2020-2023  润新知