zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    详解REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR
    HTTP Header 详解
    搜索引擎爬虫蜘蛛的useragent
    PHP防抓取数据curl 解决方法
    用curl抓取网站数据,仿造IP、防屏蔽终极强悍解决方式
    windows下 composer常见问题及处理
    Composer命令详解
    SSM框架之RestFul示例
    关于SpringMVC返回数据带斜杠字符串问题之解决方案
    js之radio应用实例
  • 原文地址:https://www.cnblogs.com/redirect/p/10066665.html
Copyright © 2011-2022 走看看