1. 一些概念

  • 单点登陆:

    • 一套公用的用户体系,登陆后,能够访问所有的系统。
    • 这只是一类解决方案的统称,在具体的实施方面,有两种策略 SAML,OAuth
  • OpenID:

    • 比如,允许使用微信/支付宝或者其他账号 登陆 其他网站
    • 只用于身份认证,允许你以同一个账号在多个网站登陆。
    • 登陆后 ,该站点无法访问你在 微信 上的数据。
  • Authentication:身份鉴别,也就是 认证(鉴别是否为合法用户)
  • Authorisation:授权(鉴别访问权限)
  • SMAL 2.0: https://zhuanlan.zhihu.com/p/...
  • OAuth :

1. token 的典型流程:

  • 用户登录的时候,服务端生成一个token(通过登录信息做数字签名,加密之后得到的字符串)返回给客户端
  • 客户端后续的请求都带上这个token
  • 服务端解析token(做解密和签名认证,判断其有效性)获取用户信息,并响应用户的请求。
  • token会有过期时间,客户端登出的时候也会废弃token,但是服务端不需要任何操作

2. session 和 token 的区别:

  • session, 要求服务端存储信息,并根据id能够检索,而 token 不需要。
  • 服务端 要 通过 token 来解析 用户身份,也需要定义好相应的协议。
  • session 一般使用cookie 来交互。token,可以是 cookie,也可以是 其他heaser,甚至可以放在请求的内容中。不使用cookie可以带来跨域的便利性
  • 很多情况下,sessin 和 token 可以一起使用。
  • token 技术 对应的标准,就是JWT

3.JWT(JSON Web Tokens)

  • 组成:

    • Header(头部)(是一个JSON 对象)

      {
        "alg": "HS256", // 表示签名的算法,默认是 HMAC     SHA256(写成 HS256)
        "typ": "JWT"  // 表示Token的类型,JWT 令牌统一写为JWT
      }
    • Payload(负载)(也是一个JSON 对象-- 用来存放实际需要传递的数据)
    {
      // 7个官方字段
      "iss": "a.com", // issuer:签发人
      "exp": "1d", // expiration time:(必须设置)
      "sub": "test", // subject: 主题
      "aud": "xxx", // audience: 受众
      "nbf": "xxx", // Not Before:生效时间
      "iat": "xxx", // Issued At: 签发时间
      "jti": "1111", // JWT ID:编号
      // 可以定义私有字段
      "name": "John Doe",
      "admin": true
    }
    • Signature(签名)

      • 对前两部分的签名,防止数据被篡改。
      • 需要指定一个密钥(secret)。
      • 采用的公式:

        • header 中的签名算法(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret)
  • JWT = Base64(Header) + "." + Base64(Payload) + "." + $Signature
  • 特点:

    • JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。
    • 发送 JWT, 要使用 https,不实用HTTPS的时候,JWT里面不要写入秘密数据。
    • 在使用过程中无法废除 某个 token,或者更改 token 的权限,也就是一旦签发就会始终有效。
  • 使用方法:

    • 客户端,得到 token 后,可以存储在 cookie里,或者localstorage 中
    • 以后的http 请求都要带着 这个token
    • 发送的时候:可以放在cookie 中,也可以放在 HTTP 请求头 信息 Authorization 字段中,还可以在 post 请求的时候放在请求数据体里。
  • 分类:

    • access token:

      • 有效期短
      • 以上的都是针对 该种 token
    • refresh token:

      • 有效期长。
      • 自身以及过期时间是 存储在服务器的数据库中的。
      • 只有在申请新的 access token 的以后才会验证,不会对业务接口响应时间造成影响,也不会一直保存在内存中以应对大量的请求。
  • 为什么要有 refresh token?

    • 目的:职能分离。refresh token 负责身份认证,access token 负责请求资源。
  • 流程:

    • client -> server: username && password
    • server: 得到token
    • server -> client: access token 、 refresh token
    • client:将 token保存在本地
    • client -> server: access token
    • server: access token 没有过期
    • server -> client: 返回数据
    • client -> server: access token
    • server: access token 过期
    • server -> client: 返回错误
    • client -> server: refresh token
    • server: 判断 refresh token 是否过期
    • server -> client: 没过期,则返回新 的 access token和 refresh token。如果过期了,需要重新登陆

4. token 和 session 的区别:

  • session:

    • 为无状态的HTTP提供持久机制。
    • 如果需要实现有状态的会话,可以增加Session来在服务端保存一些状态。
    • 只提供一种简单的认证,数据只保存在站点,不应该共享给其他网站或者第三方APP
  • token:

    • 就是一个令牌。
    • 作为身份认证安全性更好。
    • 如果你的用户数据可能需要和第三方共享,或者允许第三方调用API接口,用Token。

5. bearer token:

  • 定义:

    • 用于 OAuth 2.0 授权访问资源
    • 任何 持有 bearer 的都可以访问资源,而无需证明持有加密 key。
    • 一个 bearer 代表授权范围、有效期,以及其他授权事项。
    • 传输时,要防止泄露。
    • 有效期不能过长,过期后,可使用 refresh token 申请 更新。
  • 资源请求:

    • bearer 实现资源请求移动有 3种方式,以下的优先级依次递减。
    • Authorization Header: Authorization: Bearer mF_9.B5f-4.1JqM
    • Form-Encoded Body Parameter:

      • 使用:
      Content-Type: application/x-www-form-urlencoded
      
      access_token=mF_9.B5f-4.1JqM
      • 使用条件:

        • 头部必须包含"Content-Type: application/x-www-form-urlencoded"
        • entity-body必须遵循application/x-www-form-urlencoded编码(RFC 6749)
        • 如果entity-body除了access_token之外,还包含其他参数,须以"&"分隔开
        • entity-body只包含ASCII字符
        • 要使用request-body已经定义的请求方法,不能使用GET
    • URI Query Parameter:

          GET /resource?access_token=mF_9.B5f-4.1JqM HTTP/1.1
          Cache-Control: no-store
      • 服务端应在响应中使用 Cache-Control: private
  • WWW-Authenticate 头:

    • 在客户端未发送有效Bearer的情况下,即错误发生时,资源服务器须发送WWW-Authenticate头
    • 例: WWW-Authenticate: Bearer realm="example", error="invalid_token", error_description="The access token expired"
    • 字段用法:

      • Bearer:Beare作为一种认证类型(基于OAuth 2.0),使用"Bearer"关键词进行定义
      • realm:与Basic、Digest一样,Bearer也使用相同含义的域定义reaml
      • scope:授权范围,可选的,大小写敏感的,空格分隔的列表(%x21 / %x23-5B / %x5D-7E),可以是授权服务器定义的任何值,不应展示给终端用户。OAuth 2.0还规定客户端发送scope请求参数以指定授权访问范围,而在实际授权范围与客户端请求授权范围不一致时,授权服务器可发送scope响应参数以告知客户端下发的token实际的授权范围。下为两个scope用法实例:
       scope="urn:example:channel=HBO&urn:example:rating=G,PG-13"```
    - error:描述访问请求被拒绝的原因,字符%x20-21 / %x23-5B / %x5D-7E之内
    - error_description:向开发者提供一个可读的解释,字符%x20-21 / %x23-5B / %x5D-7E之内
    - error_uri:absolute URI,标识人工可读解释错误的页面,字符%x21 / %x23-5B / %x5D-7E之内.当错误发生时,资源服务器将发送的HTTP Status Code(通常是400, 401, 403, 或405)及Error Code如下:
    - invalid_request:请求丢失参数,或包含无效参数、值,参数重复,多种方法发送access token,畸形等。资源服务器将发送HTTP 400 (Bad Request)
    - invalid_token:access token过期、废除、畸形,或存在其他无效理由的情况。资源服务器将发送HTTP 401 (Unauthorized),而客户端则需要申请一个新的access token,然后才能重新发送该资源请求
  • bearer token response:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
   "access_token":"mF_9.B5f-4.1JqM",
   "token_type":"Bearer",
   "expires_in":3600,
   "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA"
}
```
  • 安全威胁:

    • token 伪造/修改: 攻击者伪造/修改 已有的 token,导致资源服务器授权 通过非法访问的客户端,因此需要对 token 使用数字签名或者消息认证码来保证完整性。
    • token 泄漏:本身包含认证、有效期等敏感信息,所以需要加密。
    • token 改寄:攻击者用一个访问A资源服务器的token去请求B资源服务器的资源。因此通常 token 中可以包含代表资源服务器的标识 来防止这种情况的发生。
    • token 重放:攻击者企图使用曾经使用过的token来请求资源。因此token需包含有效期(比如少于1小时)

5. 使用token需要考虑的问题

  • 如果你认为用数据库来存储 token 会导致查询时间太长,可以选择放在内存当中。比如 redis 很适合你对 token 查询的需求。
  • token 完全由应用管理,所以它可以避开同源策略
  • token 可以避免 CSRF 攻击(因为不需要 cookie 了)
  • 移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token

6. 参考:


默_hjh
32 声望1 粉丝

« 上一篇
session
下一篇 »
stoarge