ArcherWong博客
首页
博客
JWT
作者:ArcherWong
分类:web
时间:2019-01-04 10:38:34
阅读:985
[TOC] # 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,从而回避重放攻击。 2. 非标准部分可以写入用户的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; ``` 2. 使用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
标签:
上一篇:
详解网络连接
下一篇:
http报文
文章分类
css
elasticsearch
git
golang
guacamole
javascript
letsencrypt
linux
nginx
other
php
python
vue
web
阅读排行
centos7.3配置guacamole
golang笔记---关联数组(map)
letsencrypt证书-管理工具certbot
golang笔记---template模板语法
详解网络连接
友情链接
node文件
laravel-vue
ArcherWong的博客园