Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Network - 鉴权 #28

Open
tomoya06 opened this issue Sep 30, 2020 · 2 comments
Open

Network - 鉴权 #28

tomoya06 opened this issue Sep 30, 2020 · 2 comments

Comments

@tomoya06
Copy link
Owner

tomoya06 commented Sep 30, 2020

接口鉴权方式

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)

最佳实践

  • 客户端收到服务器返回的 JWT,可以储存在 Cookie 或 localStorage。客户端每次与服务器通信,都要带上这个 JWT,可以放在cookie或者HTTP请求头Authorization字段。
  • JWT TOKEN还可以继续用密钥再加密,不加密时不能将敏感信息存入其中。
  • 由于TOKEN有效期已经嵌在Payload中,所以签发之后若没有额外配置将不会主动失效。
  • 为防止盗用,TOKEN有效期不应太长,且不建议明文传输。
@tomoya06
Copy link
Owner Author

tomoya06 commented Oct 8, 2020

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
Copy link
Owner Author

tomoya06 commented Oct 8, 2020

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场景。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant