前端登录场景
前端登录场景
月晕前端登录详解
在网页上,登录几乎是每个网站都具备的功能,业界常用的方式有下面几种
- Cookie + Session 登录
- Token 登录
- SSO 单点登录
- OAuth 第三方登录
Cookie + Session 登录
基本概念
Cookie : HTTP 是一种无状态的协议,客户端每次发送请求时,首先要和服务端建立一个连接,在请求完成后会断开这个连接,这样能够节省传输时的资源,但是每次请求都是独立的,无法识别请求是否来自同一个用户,Cookie 出现了,由客户端保存的小型 key value 文件由 HTTP 服务器设置的,可以随着请求发送,交互信息
Session: 有了 Cookie,服务端可以知道用户的传来消息,但是要对这个消息进行验证,需要通过 Session,在客户端请求服务器的时候,为这次 Session 开辟内存空间,这样就可能进行登录验证了,Session 应该存在服务端中,避免客户端 Cookie 中存储敏感数据,可以存在内存中,也可以存在 redis 中
认证:Cookie/Session 认证机制就是为一次请求认证在服务端创建一个 Session 对象,同时在客户端创建一个 Cookie 对象,通过客户端传递的 Cookie 对象与服务器端的 Session 对象匹配来实现状态管理
实现流程
首次请求的时候,输入账号密码后发送 HTTP 请求,服务端验证后创建会话 ID(SessionID),并保存在内存或者数据库中,通过 set-Cookie 去设置头信息,将 sessionID 写入 Cookie 中
在次请求的时候会带上上次登录时候的 Cookie,会将 Cookie 中的 SessionId 保存并进行对比,如果一致就代表身份认证 ok
特点
- 维护成本高:服务器是集群的时候为了维护登录状态,需同步 SessionID
- 服务器内存占用多压力大
- CSRF 跨站伪造请求攻击:Cookie 被劫持就可能会受到攻击,可以使用 csrf_token(双重验证来解决)
- 扩展性不强,没有共享登录状态
- 手机请求不支持 Cookie
Token 登录
为了解决传统的 Cookie 和 Session 登录的一些痛点,出现了 Token 登录验证的方式
登录流程:
登录时,客户端通过用户名与密码请求登录–>服务端收到请求去验证用户名和密码–>验证通过后,服务端会签发一个带签名的 token,把这个 token 以响应返回给客户端–>客户端收到 token 后,储存在浏览器本地–>客户端每次调用 API 的时候会发送 Token–>服务端进行 token 鉴权
实现流程
用户在登录时,输入账号密码,服务器会验证账号密码,验证无误后会创建 Token,然后将 Token 返回给客户端,客户端将其保存下来。
下次访问的时候带上 token 即可
特点
- 无状态,可扩展:tokens 是无状态的,能够被扩展,可以打给多个机器,自身是 JSON
- 安全性
- 时效性
Token 生成方式
常见的 token 生成方式是 JWT (Json Web Token),jwt 实际上就是一个 base64 的字符串,有三个部分组成 Header、Payload、Signature,都是 json 格式
头部(Header):用于描述关于 JWT 的最基本信息,例如类型已经签名用的算法等的
1
{ "type": "JWT", "alg": "HS256" }
载荷(Payload):存放一些不敏感的信息,比如用户 ID 之类的
签名(Signature):将上面拼接完的字符串用 HS256 算法进行加密。在加密的时候,我们还需要提供一个密钥(secret)。加密后的内容也是一个字符串,最后这个字符串就是签名,把这个签名拼接在刚才的字符串后面就能得到完整的 jwt。header 部分和 payload 部分如果被篡改,由于篡改者不知道密钥是什么,也无法生成新的签名部分,服务端也就无法通过,在 jwt 中,消息体是透明的,使用签名可以保证消息不被篡改。
SSO 单点登录
单点登录(Single Sign On),即 SSO,目前比较流行的企业业务整合的解决方案,SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统
SSO 一般需要一个独立的认证中心(passport),子系统的登录均通过 passport,子系统本身将不参与登录操作,当一个系统成功登录以后,passport 将会颁发一个令牌给各个子系统,子系统可以拿着令牌会获取各自的受保护资源,为了减少频繁认证,各个子系统在被 passport 授权以后,会建立一个局部会话,在一定时间内可以无需再次向 passport 发起认证。
登录流程
- 用户首次访问时,需要在认证中心登录
- 比如用户访问 a.com 下面的 pageA 的时候,由于没有登录,则会重定向到认证中心,并带上回调地址
www.sso.com?return_uri=a.com/pageA
,直接进入对应页 - 用户输入认证信息
- 认证中心认证有效后,重新向到
a.com/PageA?ticket=exploison
,带上授权码,并将认证中心 sso.com 的登录态写入 Cookie 中 - 在 a.com 服务器中,拿着 ticket 向认证中心确认,授权码 ticket 真实有效
- 验证成功后,服务器将登录信息写入 Cookie,返回给客户端,并保存下来
- 继续访问 a.com 下的别的信息时,由于 a.com 存在已登录的 Cookie 信息,所以服务器端直接认证成功。
- 如果认证中心登录完成之后,访问 b.com 下的页面
- 由于认证中心存在之前登录过的 Cookie,所以也不用再次输入账号密码,下发 ticket 给 b.com 即可。
退出登录流程
比如在c.com
的时候
- 清空 c.com 中的登录态 Cookie
- 请求认证中心 sso.com 中的退出 api
- 认证中心遍历发过 ticket 的所有产品,并调用 api 完成退出
特点
- 简化管理、提高用户效率、提高开发人员效率
- CPU 开销大、安全隐患、重构困难
OAuth 第三方登录
第三方登录,实质就是 OAuth 授权。用户想要登录 A 网站,A 网站让用户提供第三方网站的数据,证明自己的身份。获取第三方网站的身份数据,就需要 OAuth 授权。
为用户资源的授权提供了一个安全又简易的标准,OAuth 不会涉及到第三方的账号密码信息,即可获取到用户资源的授权
流程
- 第三方要求用户给予授权
- 用户同意授权
- 根据上一步获得的授权,第三方向认证服务器请求令牌(token)
- 认证服务器对授权进行认证,确定后发放令牌
- 第三方使用令牌向资源服务器请求资源
- 资源服务器使用令牌向认证服务器确认令牌的正确性,确定后提供资源
具体流程(以 QQ 为例)
QQ 登录 OAuth2 的处理流程主要是下面
- 获取 access_token
- 根据 access_token 获取对应用户身份的 openid
- 根据 access_token 与 openid 调用 OpenAPI,来请求访问或修改用户授权的资源