1. 一些概念
-
单点登录:html
- 一套公用的用户体系,登录后,可以访问全部的系统。
- 这只是一类解决方案的统称,在具体的实施方面,有两种策略 SAML,OAuth
-
OpenID:web
- 好比,容许使用微信/支付宝或者其余帐号 登录 其余网站
- 只用于身份认证,容许你以同一个帐号在多个网站登录。
- 登录后 ,该站点没法访问你在 微信 上的数据。
- 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 对象)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 请求的时候放在请求数据体里。
-
分类:cookie
-
access 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. 参考: