目录
0x01 概念
首先给出这几个易混淆的概念定义
认证(Identification): 根据声明者持有的特定信息,来确认声明者的身份
- 例如身份证、用户名/密码、手机(包括短信、二维码、手势密码)、电子邮箱、生物特征(虹膜、面部、指纹、语音等)
- 高安全要求的场景下,会使用多种认证方式组合进行身份校验,即多因素认证
授权(Authorization): 资源所有者委派执行者,赋予其指定范围的权限,执行对资源的操作
- 授权实体例如银行卡、门禁卡、钥匙、证书等
- 例如web服务的session机制、浏览器的cookie机制、授权令牌token等
鉴权(Authentication): 对一个声明者的身份权利的真实性进行鉴别
- 授权和鉴权是一个一一对应的流程,有授权才会去鉴权
权限控制(Access/Permission Control): 将可执行的操作定义为权限列表,然后判断操作是允许/禁止
- 权限是将操作人的行为抽象化的一个概念
这几个概念之间的关系:认证 -> 授权 -> 鉴权 -> 权限控制
一般情况下认证/授权同时发生,认证即授权,然后在后续行为中进行鉴权和权限控制
认证和鉴权的异同:
- 认证确认的是声明者的身份,鉴权则是对声明者声明的权限进行确认
- 认证需要通过声明者独特的信息进行识别,鉴权则是通过鉴别授权过程中定义的某个媒介,这个媒介具有真实有效、不可篡改、不可伪造等特性
0x02 前端-后端授权/鉴权方案
目前常用的几种方案
- Http Basic Authentication
- session-cookie
- token/jwt
- OAuth
2.1 Http Basic Authentication
遵守HTTP协议实现的基本授权方式
HTTP协议定义了通信过程中服务器对客户端的用户身份进行认证的基本方法
具体流程:
-
1、客户端向服务端请求数据,请求的数据包括
Get /index.html HTTP/1.0 Host:www.google.com
-
2、服务器返回401,提示用户身份尚未被认证
HTTP/1.0 401 Unauthorised Server: SokEvo/1.0 WWW-Authenticate: Basic realm=”google.com” Content-Type: text/html Content-Length: xxx
-
3、客户端收到401的返回时,会自动弹出一个登录窗口,要求输入用户名和密码
-
4、用户输入用户名和密码后,浏览器会自动对用户名/密码进行加密编码,并将结果放入请求中
Get /index.html HTTP/1.0 Host:www.google.com Authorization: Basic d2FuZzp3YW5n
-
5、服务器收到请求后,会取出
Authorization
字段的值解密解码,然后将用户名和密码与数据库进行对比验证,通过后则返回客户端请求的资源
这种认证方式的好处是,非常容易实现,基本所有流行的浏览器都支持,但是此认证方式依赖客户端和服务器主机之间的安全连接,否则极易拦截客户端发送的密钥及服务端返回的信息;另一个问题是HTTP协议没有提供机制清除浏览器中的认证信息,除非标签页或浏览器关闭、或用户清除历史记录,即服务器无法主动完成用户注销,因此此认证方式几乎很少被公开访问的互联网网站使用,一般是用于小型私有系统,如路由器网页管理接口
2.2 session-cookie
- cookie
HTTP协议是一个无状态的协议,为了让服务器区分不同的客户端,引入cookie机制来管理服务器/客户端之间的状态标识;具体来说,cookie就是服务器为客户端分配的一个标识客户端身份的字段
原理:客户端首次向服务器发送请求时,服务器会为其分配cookie并存放到响应消息的特定字段中,客户端收到响应消息会解析并存储该字段,在下次再发送请求时就会在请求头部带上这个字段,因此服务器就能区分不同的客户端,以及客户端配置的各种偏好要求
- session
session的抽象概念是会话,是无状态协议通信过程中,为了实现中断/继续操作,将用户和服务器之间的交互进行的一种抽象;具体来说,是服务器生成的一种Session结构,可以通过多种方式保存,如内存、数据库、文件等,大型网站一般有专门的session服务器集群来保存用户会话
原理:用户首次发送请求时,服务器自动为该用户创建特定的session/session ID,来标识用户并跟踪用户当前的会话过程,浏览器收到响应获取会话信息,会在下一次请求时带上session ID,服务器提取后会与本地保存的session ID进行对比找到该特定用户的会话,进而获取会话状态
会话可以设置过期时间,超过时间限制服务端就销毁session,当然也可以对session进行长期保存,但是会造成数据库极速膨胀
异同:
cookie通常保存在客户端,除了包含用户信息也可以包含一些用户配置,如保存密码、设置喜好等,可见且易本地编辑,可能被拷贝;
session通常保存在服务器上,无法伪造,但是session在客户端保存标识时可能会借助cookie机制;
cookie支持跨域名访问,session则仅对当前域名有效
具体流程:
- 用户使用账号密码请求登录;
- 服务器验证用户身份后,创建session并分配唯一标识session ID,记录用户的认证状态,并将session ID放在响应头中返回给客户端(这一步中,可以使用服务端私钥对其进行签名,非必须);
- 客户端解析响应头,将服务端分配的session ID保存在本地cookie中,下一次请求时会在请求头中附带cookie信息;
- 服务端接收请求时解析头部的session ID,与本地保存的session进行对比校验请求的合法性。
2.3 token
token是一个令牌,客户端访问服务器时,验证通过后服务端会为其签发一张令牌,之后,客户端就可以携带令牌访问服务器,服务端只需要验证令牌的有效性即可。token通常包含用户信息、时间戳、哈希签名。
具体流程:
- 客户端输入用户名和密码请求登录;
- 服务器收到登录请求,验证用户名和密码,验证成功后,为客户端签发一个token并返回;
- 客户端收到服务端分配的token,保存在本地,如cookie或storage中,后面客户端每次向服务端请求资源时,只需要携带服务器分发的token;
- 服务端只需要验证客户端请求中的token,成功即返回请求数据,否则返回401鉴权失败。
token与session-cookie:
- token的作用有点像session-cookie机制中的sessionid,但是sessionid只是一个唯一的字符串标识,真正登录状态的凭证是保存在服务端的,而token本身就是一个登录状态凭证,但是token相比sessionid更大更占带宽,加解密也更消耗性能;
- session需要在服务端做持久化占据较大存储空间,token则自身就携带用户信息更具扩展性;
- session认证需要cookie配合的,因此只能在浏览器中使用,且浏览器还不能禁用cookie,在app端就无法使用,token则丰富了客户端类型;
- 而且在HTTPS下使用cookie容易遭受CSRF跨站请求伪造攻击;
- 另外,session-cookie中的sessionid在整个会话期间有效,token则可以动态改变;
- 最后,token验证方式更为灵活,有多种解决方案如JWT,而且可以基于token验证实现统一的鉴权服务
2.4 JWT(Json Web Token)
Auth0提出的对Json进行加密签名实现授权验证的方案就是一种基于token的解决方案,原理是用户登录成功后服务器将要返回的JSON
对象签名加密后返回,用户下次访问服务器就会携带这个授权令牌。
JWT通常包含头部(Header)、负载(Payload)和签名(Signature),由这三部分拼接而成
- 头部是一个JSON对象,描述JWT的元数据,如类型、加密算法
- 负载也是一个JSON对象,存放实际传输的数据,一般存放用户身份信息和描述字段
- 签名是对头部和负载的签名,服务端解密,用户数据验证防篡改
JWT默认不加密,也可以自己实现加密,因此不建议写入隐私数据,也不应该使用HTTP传输;
JWT本身包含认证信息,一般有效期都较短;
JWT除了用于认证还可以用于交换信息减少服务器数据库查询操作;
JWT机制中服务器不保存session,因此一旦签发到期之前始终有效
2.5 OAuth(Open Authorization)
OAuth是一种开放标准的授权机制,即允许用户授权第三方访问服务提供系统中的信息,第三方会显式向用户请求授权,然后生成一个短期令牌,无需提供用户名密码,保护用户数据的隐私
OAuth协议包含1.0和2.0版本,OAuth2.0授权验证流程更为简单安全,也是目前的主流方式,常见的厂商有支付宝、微信等。
具体流程:
- 第三方显式向用户请求授权
- 用户授权后,服务器返回一个用户凭证,如授权码
- 第三方拿这个用户凭证请求服务器授权
- 服务器校验后,返回资源访问的凭证,即短期令牌
- 第三方发送凭证向资源服务器请求相关资源
- 资源服务器验证凭证后,返回请求的资源
注意,OAuth提供了四种授权方式,包括授权码(authorization-code)、隐藏式(implicit)、密码式(password)和客户端凭证(client credentials),不管哪种方式,第三方都需要事先向系统注册备案,拿到识别自己身份的客户端ID和客户端密钥
OAuth提高了用户体验,缩短了用户注册和登录的时间