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

什么是单点登录? #2

Open
nonocast opened this issue Mar 1, 2020 · 0 comments
Open

什么是单点登录? #2

nonocast opened this issue Mar 1, 2020 · 0 comments

Comments

@nonocast
Copy link
Owner

nonocast commented Mar 1, 2020

OAuth 2.0 是目前最流行的授权机制,用来授权第三方应用,获取用户数据。

阮一峰的文章写的已经非常清楚了,我简单总结一下我对SSO的观点。

为什么需要单点登录?

简单阐述一下动机,比如你要开发一个邮件App,用户通过"登录"可以获取自己gmail邮件,最简单的就是你给用户一个登录界面输入用户在google的用户名和密码,但这个时候用户就会担心现在你(App的供应商)有了用户名和密码,就可以用这个密码去gmail登录进而看到所有用户邮件,这个肯定不行, 但其实google也希望第三方App在不接触最终用户的用户名和密码的情况下来扩展自身生态。

基于资源方、第三方(ISV)和终端用户的几方面诉求,就产生了OAuth (RFC6749),现在的OAuth2.0在2012年定稿,所以已经非常成熟了。

但很多人接触OAuth是来自于另外一个场景,公司需要开发两个网站共享一套登录,所以很多人会认为OAuth是用来做身份验证的。

其实不管哪种场景,殊途同归,就好比刀可以切菜,也可以砍人。你把底层的原理想明白就ok。

服务接口的登录设计

我是在做前后端分离的时候才真正开始接触单点登录,当时后端采用node,前端采用react,如果在不借助cookie和session的方式下如何设计登录和授权方式。最终兜兜转转才发现OAuth2就是最好的解决方案:

  • backend service: 对应资源方
  • react webapp: 对应第三方App

你就会发现原来是react这个webapp需要通过OAuth方式去获取backend service中的数据,这就回到文中第一句的定义。

所以一切需要问service获取数据的登录授权才会归结为OAuth这个标准下,那为什么OAuth会有多种模式呢?

  • Authorization Code (授权码)
  • Implicit (隐藏方式)
  • Password (密码)
  • Client Credentials (客户端凭证)
  • Device Code (设备码)

最常见的是授权码方式,第三方引用先申请一个授权码,然后再用该码获取令牌,大致流程如下:

  • 访问webapp.com,然后点击登录,此时跳转到service的authorize,这里要注意,浏览器会在跳转到service时携带service域的cookie
  • 如果检查到cookie就表示用户之前已经登录,302到用户注册的callback或携带过来的callback参数,即返回到第三方应用的后台,url中会携带授权码(code),第三方应用后台根据code获取service token,这个步骤在第三方后台完成,后台根据token来获取用户信息和授权数据,渲染页面返回浏览器。(第三方应用的后台和页面的关系可由他们的cookie/session来维系,这个不在OAuth的范围内)
  • 如果检查到没有service cookie, 则给出login页面,用户登录后POST回service authorize进行验证,通过则callback回第三方应用后台。
  • 借助service域cookie的延续性实现了“记住密码”功能

这里需要注意2点:

  • 302是发生在用户侧,即浏览器,浏览器拿到302的http response后进行重定向
  • cookie是不安全的,即使是SSO也不能保存password,不管是明文还是密文,一定会被劫持,所以只能保存有时效性的token/refresh token来实现"记住密码"的机制

在充分理解授权码方式后,就引入了第二个问题,如果webapp是一个react,你也可以理解为html中包含了Javascript, 即第三方应用没有后台,只有前端,所以这个时候service在得到cookie后应直接callback回前端页面,而不是第三方应用的后端。

所以在开发前后端分离的应用时应该选择Implicit方式。

最后来看Password和Credentials,事实上是作为前面的补充,比如你做一个Digital Signage (信息发布)或者kiosk, 只是用来展示信息的应用,就需要用到Credentials方式,后台需要管理设备对应的凭证。

而Password更多的是用在命令行和scripting,即非浏览器环境,用户可以确保安全的场景下使用,所以很多第三方的服务是关闭Password这种模式的。

参考阅读:

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

No branches or pull requests

1 participant