tomoya06 / web-developer-guidance

Actually it's just a notebook for keeping down some working experience.
4 stars 0 forks source link

Network - 鉴权 #28

Open tomoya06 opened 3 years ago

tomoya06 commented 3 years ago

接口鉴权方式

1. SESSION

登录之后为请求方提供一个session id,对应的登录信息由服务端存储,客户端以cookie的形式保存session id,并在随后的请求中都带上session id。服务器会为每个session设置有效期,失效之后会将session删除。

Java端可以调用session.invalidate()方法主动让session失效。更多用法参考知乎博客

2. JWT TOKEN

JWT,全称Json Web Token。与session不同,JWT方案是让客户端保存会话数据,每次请求都发回服务器。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名。

token格式

token由服务器生成,发放给客户端。

image

token = (Header).(Payload).(Signature)

Header和Payload的完整格式参考阮一峰的博客。Signature是对两者的签名,防止数据篡改。签名使用的密钥仅有服务器知道,签名公式如下:

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

最佳实践

tomoya06 commented 3 years ago

3. OAuth 2.0

OAuth 2.0 是一种授权机制,主要用来颁发token。RFC标准解释了OAuth如下:OAuth 引入了一个授权层,用来分离两种不同的角色:客户端和资源所有者。资源所有者同意以后,资源服务器可以向客户端颁发令牌。客户端通过令牌,去请求数据。

最佳实践

请求url、参数、返回样例可参考阮一峰的博客

  1. 第三方客户端申请token之前,都必须先到系统备案(注册应用),说明自己的身份,然后会拿到两个身份识别码:客户端 ID(client ID)和客户端密钥(client secret)。
  2. 客户端申请token
  3. token用于调用资源方的API接口时鉴权用,所以之后的API请求都会在header带上Authorization字段
  4. token会有有效期。一般在申请token时,资源方还会另外提供一个refresh token用于获取新的token。只需发送一次token更新请求即可获取新的有效token(grant_type=refresh_token

申请token

OAuth 2.0 规定了四种获得令牌的流程。开发者可以选择最适合自己的那一种,向第三方应用颁发令牌。下面假设B是资源所有者,A是客户端。

授权码模式

特点:最常用,安全性最高。它适用于那些有后端的 Web 应用,授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。

流程:

  1. A 网站提供一个链接,指定了redirect_uri,用户点击后就会跳转到 B 网站的登陆授权页。
  2. B 网站会要求用户登录,然后询问是否同意给予 A 网站授权。用户表示同意,这时 B 网站就会跳回redirect_uri,并附带一个授权码。
  3. redirect_uri也是A 网站可控的,所以这时A就拿到了授权码,然后可以在后端向B请求access token,请求时会指定另一个redirect_uri
  4. B收到请求,就会颁发access token。具体做法是向第二个redirect_uri指定的网址,发送一段 JSON 数据。
  5. A后端收到token。

隐藏式

特点:把令牌直接传给前端,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。

流程:

  1. A 网站提供一个链接,指定了redirect_uri,要求用户跳转到 B 网站,授权用户数据给 A 网站使用。
  2. 用户跳转到 B 网站,登录后同意给予 A 网站授权。这时,B 网站就会跳回redirect_uri参数指定的跳转网址,并且把令牌作为 URL 锚点参数(eg.: https://a.com/callback#token=ACCESS_TOKEN),传给 A 网站。
  3. A直接在前端拿到token。

令牌的位置是 URL 锚点(fragment),而不是查询字符串(querystring),这是因为 OAuth 2.0 允许跳转网址是 HTTP 协议,因此存在"中间人攻击"的风险,而浏览器跳转时,锚点不会发到服务器,就减少了泄漏令牌的风险。

密码式

特点:允许用户把用户名和密码,直接告诉该应用,应用直接用来申请令牌。

流程:

  1. A 网站要求用户提供 B 网站的用户名和密码,提供之后,A 直接调用B的申请token接口来请求token(grant_type=password)。
  2. B 网站验证身份通过后,直接返回令牌。

凭证式

特点:适用于没有前端的命令行应用,即在命令行下请求令牌。这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。

流程:

  1. A 应用在命令行向 B 发出申请token请求(grant_type=client_credentials)。
  2. B 网站验证通过以后,直接返回令牌。
tomoya06 commented 3 years ago

4. SSO单点登录

单点登录(Single Sign On),简称为 SSO,是比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

最佳实践

本节参考这篇博客

CAS框架实现的SSO流程示意图如下。

image

首次登录app的流程为:

  1. 用户访问app系统,app系统是需要登录的,但用户现在没有登录。
  2. 跳转到CAS server,即SSO登录系统,即图中的CAS Server。 SSO系统也没有登录,弹出用户登录页。
  3. 用户填写用户名、密码,SSO系统进行认证后,将登录状态写入SSO的session,浏览器(Browser)中写入SSO域下的Cookie。
  4. SSO系统登录完成后会生成一个ST(Service Ticket),然后跳转到app系统,同时将ST作为参数传递给app系统。
  5. app系统拿到ST后,从后台向SSO发送请求,验证ST是否有效。
  6. 验证通过后,app系统将登录状态写入session并设置app域下的Cookie。

首次登录app2的流程如下:

  1. 用户访问app2系统,app2系统没有登录,跳转到SSO。
  2. 由于SSO已经登录了(SSO域下面也会生成一个登录cookie),不需要重新登录认证。
  3. SSO生成ST,浏览器跳转到app2系统,并将ST作为参数传递给app2。
  4. app2拿到ST,后台访问SSO,验证ST是否有效。
  5. 验证成功后,app2将登录状态写入session,并在app2域下写入Cookie。

特点

与OAuth2.0相比,两者的差异在于:

  1. 两者都需要跳转到用户管理方提供的登录页面进行登录。登录成功之后,OAuth直接重定向返回原网页,CAS则是先重定向到app的业务系统,且还需要再向SSO发送一次请求,再回到原网页。
  2. OAuth重定向返回时一并提供token,之后的请求只需在请求头带上token即可;CAS重定向到业务系统时提供的是ticket,向SSO请求确认ticket之后,SSO再返回一个sessionid,保存在cookie。
  3. 使用场景不同。Oauth适用于单个app的场景,sso适用于多个使用相同登陆体系的app场景。