什么是JWT

TOKEN

token 是一串字符串,通常因为作为鉴权凭据,最常用的使用场景是 API 鉴权。

API 鉴权

API鉴权的方式有以下几种

  • cookie + session
    和平常 web 登陆一样的鉴权方式

  • HTTP Basic

账号和密码拼接然后 base64 编码加到 header
头中
。很显然,因为账号和密码几乎是『明文』传输的,而且每次请求都传,安全性可想而知。

所以,这种方式是好少使用的

  • HTTP Digest

将账号和密码加上其他一些信息拼接然后取摘要加到 header 头中。

不过其实最大的问题还是:每次请求都要对账号、密码取一次摘要,也就是说每次请求都要有账号和密码,也就是说账号和密码要么缓存一下,要么就每次请求要去用户输一次密码,这样显然不合适。

  • Token

token通过一次登录验证,得到一个鉴权字符串,然后以后带着这个鉴权字符串进行后续操作,这样就可以解决每次请求都要带账号密码的问题,而且也不需要反复使用账号和密码。

CSRF 攻击

构成这个攻击的原因,就在于 Cookie + Session 的鉴权方式中,鉴权数据(cookie 中的
session_id)是由浏览器自动携带发送到服务端的
,借助这个特性,攻击者就可以通过让用户误点攻击链接,达到攻击效果。而 token
是通过客户端本身逻辑作为动态参数加到请求中的,token 也不会轻易泄露出去,因此 token 在 CSRF 防御方面存在天然优势

JWT 的组成

JWT 全称 JSON Web Tokens ,是一种规范化的 token。可以理解为对 token 这一技术提出一套规范,是在 RFC 7519 中提出的

组成

一个 JWT token 是一个字符串,它由三部分组成,头部、载荷与签名,中间用 . 分隔,例如:xxxxx.yyyyy.zzzzz

头部(header)

头部通常由两部分组成:令牌的类型(即 JWT)和正在使用的签名算法(如 HMAC SHA256 或 RSA.)。
例如:

{
  "alg": "HS256",
  "typ": "JWT"
}
载荷(Payload)

载荷中放置了 token 的一些基本信息,以帮助接受它的服务器来理解这个 token。同时还可以包含一些自定义的信息,用户信息交换

载荷的属性也分三类:

  • 预定义(Registered)
  • 公有(public)
  • 私有(private)

预定义的载荷

{
  "sub": "1",
  "iss": "http://localhost:8000/auth/login",
  "iat": 1451888119,
  "exp": 1454516119,
  "nbf": 1451888119,
  "jti": "37c107e4609ddbcc9c096ea5ee76c667",
  "aud": "dev"
}

这里面的前 7 个字段都是由官方所定义的,也就是预定义(Registered claims)的,并不都是必需的

  • iss (issuer):签发人
  • sub (subject):主题
  • aud (audience):受众
  • exp (expiration time):过期时间
  • nbf (Not Before):生效时间,在此之前是无效的
  • iat (Issued At):签发时间
  • jti (JWT ID):编号
签名(Signature)

签名时需要用到前面编码过的两个字符串,如果以 HMACSHA256 加密

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

加密后再进行 base64url 编码最后得到的字符串就是 token 的第三部分 zzzzz

组合便可以得到 token:xxxxx.yyyyy.zzzzz。

JWT 的使用有两种方式
  • 加到 url 中:?token=你的token
  • 加到 header 中,建议用这种,因为在 https 情况下更安全:Authorization:Bearer 你的token

JWT 在客户端的存储有三种方式

  • LocalStorage
  • SessionStorage
  • Cookie [不能设置 HTTPonly]
    值得注意的是,Cookie的这种方式有的移动端是不支持的,但是我们可以配合其他方式去使用
    最推荐的还是第三种,因为第一二种存在跨域读取限制,而 Cookie 使用不同的跨域策略

Cookie 的跨域策略

子可以读父,但是父不可以读子,兄弟之间不能互相访问

a.xxx.com 和 b.xxx.com 可以读 xxx.com,
但是 a.xxx.com 和 b.xxx.com不能互相读取,
xxx.com 也不能读 a.xxx.com 和 b.xxx.com 的

关于 token 十件必须知道的事

  1. Token 获取到后需要保存起来以便下次使用,可以选择存储在 localstorage /sessionstorage/cookie
  2. Token 是包含有效期的,你必须部署一些逻辑来进行有效期的控制
  3. localstorage /sessionstorage 的跨域限制较 cookie 更为严格,推荐使用 cookie
  4. 在你进行异步请求时,浏览器一般都会发送预检请求(option),后端应对此部署相应的逻辑
  5. 为什么会有 OPTIONS 请求 - 云 + 社区 - 腾讯云
  6. 使用 cookie 可以轻松处理一个文件下载请求,但是 token 一般都是通过 XHR
    方式进行请求的,所以你必须部署额外的逻辑。比如生成一个实时 ticket ,以 ticket 进行访问,然后校验,重定向,最后下载文件。
  7. 处理 XSS 比处理 CSRF 更容易(这一点我实在没看到他是什么个逻辑,大家可以去看看原文)
  8. token 在每次请求时都会被编码到请求中,所以请注意 token 的大小,不要编码过多数据
  9. 如果在 token 中编码敏感信息,请对 token 进行加密
  10. JSON Web Token 可以用于 Oauth2.0 的 Bearer Token 中,赋予 Oauth2.0 无状态的优势

本文转载于 skyArony

版权声明:
作者:linrux
链接:https://www.tot7.cn/technology/php/174.html
来源:Code林
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>