鉴权(authentication)是指验证用户是否拥有访问系统的权利。
传统的鉴权是通过密码来验证的。这种方式的前提是,每个获得密码的用户都已经被授权。在建立用户时,就为此用户分配一个密码,用户的密码可以由管理员指定,也可以由用户自行申请。
这种方式的弱点十分明显:一旦密码被偷或用户遗失密码,情况就会十分麻烦,需要管理员对用户密码进行重新修改,而修改密码之前还要人工验证用户的合法身份。
为了克服这种鉴权方式的缺点,需要一个更加可靠的鉴权方式。主流鉴权方式是利用认证授权来验证数字签名的正确与否。
逻辑上,授权发生在鉴权之后,而实际上,这两者常常是一个过程。
鉴权的方式
-
HTTP Basic Authentication
-
session-cookie
-
Token 验证
-
OAuth(开放授权)
HTTP Basic Authentication
HTTP Basic Authentication的授权方式是浏览器遵守http协议实现的基本授权方式,HTTP协议进行通信的过程中,HTTP协议定义了基本认证认证允许HTTP服务器对客户端进行用户身份证的方法。
Session-Cookie
HTTP Cookie(也叫Web Cookie或浏览器Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie使基于无状态的HTTP协议记录稳定的状态信息成为了可能。
cookie数据保存在客户端,session数据保存在服务端
Token 验证
token 也称作令牌,由uid+time+sign[+固定参数] token 的认证方式类似于临时的证书签名, 并且是一种服务端无状态的认证方式, 非常适合于 REST API 的场景. 所谓无状态就是服务端并不会保存身份认证相关的数据。
OAuth(开放授权)
OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAUTH是安全的。同时,任何第三方都可以使用OAUTH认证服务,任何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。
如何使用Google Oauth2.0搭建鉴权
1. 创建Google Oauth2.0 Client
这里不做详细介绍,可参考console.developers.google.com/
创建好Client后,将配置文件保存好client_id, client_secret
开启创建client下面的People API开关
2. 搭建前端请求客户端
使用Google api jdk搭建前端客户端,点击登陆调用google登陆,我们会得到google client返回的google code
这里会有几个点需要注意
-
前端请求需要赋值为off line权限,详情可参考developers.google.cn/youtube/v3/…
-
为什么不直接使用google登陆,而是使用Node作为BFF去做登陆
- 首先,由于直接使用google作为登陆使用,client_id和client_secret会直接暴露在前端代码。存在安全风险
- 不利于做权限控制扩展。当我们需要做权限控制时,直接使用前端登陆并不能很好的实现
3. 搭建Node层客户端
将从客户端中获取的google code和redirect_url(这个值为在Client配置列表中的值)发送请求Google People API。获取用户信息和acceess_token
整体流程如下:
sequenceDiagram
Browser->>Google Client: 用户点击登陆,跳转到google登陆
Google Client-->>Browser: Google Oauth Code
Browser ->> Node:将Google Code请求发送到Node BFF层
Node ->> Google Client: 将Google code 和在 Google Client 配置好的redirect url 传递给Google Client
Google Client -->> Node: 返回用户信息token过期时间
前端请求验证
前端发起请求
前端在登陆后获取access_token后,下次发送请求,将token置入http headers
后端接收请求
后端解析出token,通过Google服务验证token的有效性。如果token有效。继续请求,否则返回401。前端重新登陆。
大致流程如下
sequenceDiagram
Browser->>Node: 前端发送数据接口请求
Node-->>Browser: Node验证Token的有效性
alt 如果token有效
Node ->> Node: 继续请求数据
Node -->> Browser: 正常返回数据
else token无效
Node -->> Browser: 前端跳转到登陆页重新登陆
end
注意点
-
由于Google服务最近经常性的不稳定,导致登陆服务无法使用。推荐使用OAuth2.0 + JWT 的方案。在使用google登陆后,将用户信息通过JWT生成token返回给前端。这样每次接口token的校验就不用依赖于google服务
-
上文也提到过权限控制。由于最近项目使用到NestJS。所以可以参考使用装饰器的方式在Controller层控制访问权限。通过Gruad守卫去做鉴权
结束语
2022.1.28
木更