网络中的Auth身份认证和授权
1. 认证和授权
首先,需要对齐概念:
认证:authentication(AuthN),身份认证
授权:authorization(AuthZ),权限授权
例子:
你要登陆论坛,输入用户名张三,密码1234,密码正确,证明你张三确实是张三,这就是 authentication;
检查用户张三是个版主,所以有权限加精和删别人帖,这就是 authorization。
2. 认证场景
-
单点登录(Single Sign-on, SSO),用同一套账号访问不同的服务。比如同一个公司账号可以访问不同的服务(HR系统/开发系统/内容管理系统)等。
SSO的核心是实现一个统一的身份提供商、统一的一套凭据系统,各个资源服务器都向该身份提供商验证凭据,即可实现。 -
社交账号登录(Universal Login/Social Login),允许用户用不同社交平台注册的账号登录同一个系统。例如小红书APP的登录页支持用微信、微博账号登录。
微信、微博等社交平台相当于不同的身份提供商。Social Login的实现方法是代理模式:仍然实现一个统一的、中心化的身份提供商,而该提供商作为社交平台身份提供商的代理,将它们的凭据适配成一套统一的凭据,从而用户可以直接使用其在社交平台上注册的身份进行认证。
3. 认证流程
OAuth 2 是一个授权框架,或称授权标准,它可以使第三方应用程序或客户端获得对HTTP服务上(例如 Google,GitHub )用户帐户信息的有限访问权限。
OAuth 2 通过将用户身份验证委派给托管用户帐户的服务以及授权客户端访问用户帐户进行工作。综上,OAuth 2 可以为 Web 应用 和桌面应用以及移动应用提供授权流程。
角色
- 资源所有者(Resource Owner)
资源所有者即代表授权客户端访问本身资源信息的用户。例子中为用户 - 资源服务器(Resource Server)
资源服务器托管了受保护的用户账号信息。例子中为微信/微博 - 授权服务器(Authorization Server)
授权服务器验证用户身份然后为客户端派发资源访问令牌。例子中为微信/微博 - 客户端(Client)
客户端即代表意图访问受限资源的第三方应用。在访问实现之前,它必须先经过用户者授权,并且获得的授权凭证将进一步由授权服务器进行验证。例子中为小红书
认证流程
在用户交互层面,可看下图

在请求时序上,可看下图

Authrization Request
客户端向用户请求对资源服务器的authorization grant。
Authorization Grant(Get)
如果用户授权该次请求,客户端将收到一个authorization grant。
Authorization Grant(Post)
客户端向授权服务器发送它自己的客户端身份标识和上一步中的authorization grant,请求访问令牌。
Access Token(Get)
如果客户端身份被认证,并且authorization grant也被验证通过,授权服务器将为客户端派发access token。授权阶段至此全部结束。
Access Token(Post && Validate)
客户端向资源服务器发送access token用于验证并请求资源信息。
Protected Resource(Get)
如果access token验证通过,资源服务器将向客户端返回资源信息。
认证方式
授权许可类型取决于应用请求授权的方式和授权方服务支持的 Grant Type。OAuth 2 定义了四种 Grant Type,每一种都有适用的应用场景。
- Authorization Code
最常使用的一种授权许可类型,即为上图所示 - Implicit
结合移动应用或 Web App 使用。和Authorization Code授权流程基本一致,只是去除了请求和获得authorization code的过程,而用户点击授权后,授权服务器也会直接把access token放在redirect_uri中发送给User-agent(浏览器) - Resource Owner Password Credentials
适用于受信任客户端应用,例如同个组织的内部或外部应用。 - Client Credentials
适用于客户端调用主服务API型应用(比如百度API Store)
授权码flow比隐式flow更加安全:
- access token不会被直接暴露在地址栏,减少了凭据暴露的风险;
- 请求access_token时,需要提供客户端密钥。而且在开始认证时需要客户端提供自定义的state值,可以防止非法客户端。
4. Jwt
JSON Web Token的缩写。JWT是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。可指导将用户授权等数据通过加密的方式存储在Cookie等容器中。
- 结构
JWT主要包含三个部分之间用英语句号'.'隔开
Header 头部:包含token类型和采用的加密算法
Payload 负载:包括以下标准字段和用户自定义数据
iss: 该JWT的签发者
sub: 该JWT所面向的用户
aud: 接收该JWT的一方
exp(expires): 什么时候过期,这里是一个Unix时间戳
iat(issued at): 在什么时候签发的
Signature 签名:用于对JWT的头部和负载整合的一个签名验证
- 容器
客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。
客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。大部分场景是使用Bearer Header的
5. Cookie & Session
Cookie
Cookie翻译过来是‘ 小甜饼’,Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,实际上Cookie是服务器在本地机器上存储的一小段文本,并随着每次请求发送到服务器。也是实现Session的一种方式。
Session
是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中
服务端执行session机制时候会生成session的id值,这个id值会发送给客户端,客户端每次请求都会把这个id值放到http请求的头部发送给服务端,而这个id值在客户端会保存下来,保存的容器可以是cookie,但是当我们完全禁掉浏览器的cookie的时候,也可以放在url参数中
区别
- cookie数据存放在客户的浏览器(客户端)上,session数据放在服务器上,但是服务端的session的实现对客户端的cookie有依赖关系的;
- cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session;
- session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。考虑到减轻服务器性能方面,应当使用COOKIE;
- 单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能超过3K;
6. 参考
https://medium.com/@darutk/diagrams-and-movies-of-all-the-oauth-2-0-flows-194f3c3ade85
https://www.zybuluo.com/wddpct/note/1130423
https://juejin.im/post/5aa783b76fb9a028d663d70a
https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html