Skip to main content

2 posts tagged with "sso"

View All Tags

基于Oauth2.0,JWT的SSO单点登录

· 3 min read

需求场景

当公司网站越来越多时,还是希望账号能打通,登录公司a网站后,打开b网站需要登录时可以不用输密码直接登录,主要是方便用户登录,简化流程,不用记那么多的密码。单点登录可以说是这一痛点的解决方案了。

常用解决方案

方案一:基于cas认证的单点登录

如果公司使用java技术栈,接入开源的cas是很不错的。

apereo/cas: Apereo CAS - Identity & Single Sign On for all earthlings and beyond. (github.com)

方案二: 基于oauth2.0授权的单点登录

研究下来,发现oauth2.0授权和cas认证的核心流程思想基本一样。没啥太明显的区别。cas是个开源的框架,直接接入,开箱即用,省心。而oauth2.0只是个授权协议规范而已,具体怎么实现要自己去写,目前网上也没有什么比较好的类似于cas这种可以开箱即用,稳定维护的项目。所以与其接入一个不怎么靠谱的开源项目,不如搞懂流程,方便后续的踩坑。

  1. 用户访问a网站需要登录,a网站后台跳转sso认证中心,
  2. sso认证中心根据cookie判断用户未登录,弹出登录页面
  3. 用户填完密码,sso校验后生成一次性鉴权码code,设置cookie,session 并携带code重定向至a网站前端页面
  4. 前端页面获取url参数中的code,向a网站后台发送ajax请求
  5. 后台接收到code请求sso认证中心
  6. sso认证中心返回access_token
  7. 后台获取accessToken并保存,返回前端自己的鉴权accessToken
  8. 前端获取a网站的accessToken,登录成功
  9. 用户访问b网站要登录,b网站后台跳转sso认证中心
  10. 由于访问a网站时,sso留下了cookie,现在sso根据cookie和session知道用户已经登录过,不再弹出登录框,直接返回code
  11. 后续流程保持不变

方案三:基于第三方收费的sso服务

相关开源项目

  1. apereo/cas: Apereo CAS - Identity & Single Sign On for all earthlings and beyond. (github.com)
  2. authelia/authelia: The Single Sign-On Multi-Factor portal for web apps (github.com)

SPA应用Oauth2.0登录accessToken的获取

· 5 min read

需求场景

之前在做微信公众号开发时,一直是前端需要登录时,跳转后台提供的登录页面,后台会重定向至微信的用户授权页面,用户点击登录之后微信会回调到后台的登录结果页并且携带code,后台结果页拿到code,调用微信的接口获取accessToken,然后将accessToken通过重定向url参数的方式返回到SPA。这样虽然前端部分简化了登录流程,但是也带来一个安全隐患。accessToken是通过url参数重定向到前端的,如果用户直接分享这个带accessToken的页面,就会出现accessToken泄露的问题,未登录的用户打开会变成已经登录的状态。之前为了解决这个隐患,都是前端在获取accessToken的同时,在url中删除accessToken参数并刷新页面。虽然能解决问题,但是不是很优雅,总觉得这样不好,更希望accessToken是通过cookie httpOnly方式获取,这样在url上就不会体现,安全上要好很多。也不需要做url参数隐藏的处理。

常规方案

更通用的方案是前端去重定向至微信用户授权页面,用户授权后再重定向至前端页面并且携带code,前端再通过ajax请求后台获取到accessToken。这样的话,accessToken就不会暴露在url上面。不过依旧有一个问题,就是code也是通过url参数传递到前端的,那还是绕不过一个问题,用户直接将带code的页面分享出去。搜了半天也没看到有人有类似的疑问。我的考虑是获取code的页面往往是一个专门用来处理登录问题的路径如/login?code=这个页面只会短暂停留,ajax获取到accessToken后就会跳走,用户不会或者来不及分享这个页面。此外最重要的这个code是只能使用一次的,登录了就不能使用了。accessToken不一定都会这么做。

2022-5-9更新

常规方案和我之前使用的方案其实核心就一点不同,前端是直接获取accessToken还是先获取code,再通过code获取accessToken。这就要回到oauth2.0设计的初衷了,他为什么需要一个中间的code,而不直接返回accessToken呢?我之前的做法其实就相当于丢弃了oauth2.0的code,直接获取accessToken。后来才发现原来我所考虑的弊端就是oauth2.0设计code的原因啊,就是比直接获取accessToken安全了一丢丢。之前看Oauth2.0的介绍时也只是知道流程,确实没考虑过人家为什么要多此一举,设计一个中间code。至于为什么没有人和我有一样的安全疑问,估计一种是和我一样知道怎么用不知道为什么这么设计的,我也不关心你们为啥这么设计,反正我按你的规范来了,一种是真的理解了oauth2.0规范也就没啥疑问了。

相关参考

https://jcbaey.com/oauth2-oidc-best-practices-in-spa/