SSO单点登录对比分析

[复制链接]
发表于 2026-8-14 15:04:38 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
 弁言:

单点登录的英文名叫做:Single Sign On(简称SSO)。
指在同一帐号平台下的多个应用系统中,用户只需登录一次,即可访问全部相互信任的系统,实现多个系统,统一登陆。
本文重要介绍了常见单点登录流程,并对三种登录授权方式原理做了分析比较:cookie,cas,oauth2。
 
可以将单点登录简单分为:同根域单点登录、不同根域下单点登录。
 
一、同根域Cookie登录

Cookie和Session是相对的概念,都是基于key-value布局存储数据,不同是一个用在客户端一个用在服务端。
Cookie可以应用在很多场景,如一些内网后台管理系统、Portal门户、SSO统一登录、追踪用户的身份、根据特定用户进行推送或推荐等…
默认环境下,Cookie只能在同一域名下使用,通过设置domain为根域名,则Cookie可以实现同根域下共享,同根域名下基于cookie就可以方便实现SSO登录;在某些约束下,也可以实现跨域的cookie共享。
 
1.1 同根域下单点登录:

一般一个企业只会有一个主域名,通过二级域名区分子系统。举个例子:一个企业中有三个子系统(app1.domain.com、app2.domain.com、sso.domain.com),根域名同为domain.com。
登录过程:登录sso.domain.com后,通过http response写入cookie信息,包含了登录的sessionId等信息,domain设置为根域 domain.com;用户访问app1和app2时服务器就可以获取到sessionId,验证用户为登录状态,用户在浏览器上就可以正常获取app1和app2的资源。
简单易用缺点也比较显着:
cookie中如果存放了用户的敏感信息,一旦被窃取(用户的Cookie大概会由于网站的XSS漏洞而被盗取),这个负面影响大。
如果大量的用户信息放入cookie,对浏览器端压力较大,同时cookie存储的信息量大小有限不够轻量级,跨域环境下将会带来一定的麻烦。
 
1.2 cookie共享代码实例

搭建了基于SpringBoot的HTTPS服务,使用keytools生成了证书,SSL配置:
 
  1. server:
  2.   port: 9043
  3.   ssl:
  4.     key-store: classpath:ssLserver.jks
  5.     key-store-password: '@lmggTy6XNZmJwu7'
  6.     key-store-type: JKS
复制代码
 
注:为了消除浏览器安全提示,必要将证书导入信任证书列表中。
并修改host文件,配置域名映射,均指向本机,类似:
 
  1. 127.0.0.1       app1.domain.com
  2. 127.0.0.1       app2.domain.com
复制代码
 
关于Cookie共享的代码验证,分5个场景:
(1)  设置默认cookie
请求: https://app1.domain.com:9043/setDefaultCookie?name=defaultCk&value=ckValue
 
  1. ResponseCookie cookie = ResponseCookie.from(name, value)
  2.                 .httpOnly(true)//httpOnly  防止XSS漏洞js读取cookie
  3.                 .secure(true)
  4.                 .path("/")
  5.                 .maxAge(3600)
  6.                 .build();
  7.         response.setHeader(HttpHeaders.SET_COOKIE, cookie.toString());
复制代码
 
(2)  设置根域名cookie: domain.com
请求:https://app1.domain.com:9043/setRootCookie?name=rootCk&value=rtCkValue
 
  1. ResponseCookie cookie = ResponseCookie.from(name, value)
  2.                 .httpOnly(true)
  3.                 .secure(true)
  4.                 .domain("domain.com")
  5.                 .path("/")
  6.                 .maxAge(3600)
  7.                 .build();
  8.         response.setHeader(HttpHeaders.SET_COOKIE, cookie.toString());
复制代码
 
访问https://app2.domain.com:9043/printCookie 可发送根域名的cookie
 
(3)  不同子域名cookie:app2.domain.com ✘
请求:https://app1.domain.com:9043/setOtherDomainSameRootCookie?name=sameRoot&value=Val
 
  1.         ResponseCookie cookie = ResponseCookie.from(name, value)
  2.                 .httpOnly(true)
  3.                 .secure(true)
  4.                 .domain("app2.domain.com")
  5.                 .path("/")
  6.                 .maxAge(3600)
  7.                 .build();
  8.         response.setHeader(HttpHeaders.SET_COOKIE, cookie.toString());
复制代码
 
(4)  设置不同根域名cookie: app1.host.com ✘
请求:https://app1.domain.com:9043/setOtherDomainDiffRootCookie?name=diffRoot&value=val
 
  1. domain("app1.host.com")
复制代码
 
(5)  设置跨域共享cookie: app1.host.com
请求:https://app1.domain.com:9043/setNoneSameSite?name=noneSameSiteCk&value=val
 
  1. ResponseCookie cookie = ResponseCookie.from(name, value)
  2.                 .httpOnly(true)
  3.                 .secure(true)
  4.                 .path("/")
  5.                 .maxAge(3600)
  6.                 .sameSite("None")
  7.                 .build();
  8.         response.setHeader(HttpHeaders.SET_COOKIE, cookie.toString());
复制代码
 
跨域获取:https://app2.domain.com:9043/printCookie 是无法获取cookie的。现实上完整描述应该是“跨域请求获取”。
 
跨域请求获取又可以细分为:基于Form的表单请求、Ajax跨域请求
Form表单跨域请求:

某高仿APP1提供了一个页面https://app1.host.com:9043/indexPage 如下:
 
  1. <form id="fm_crossDomainForm" method="post">
  2. </form>

  3.      Form提交
复制代码
 
用户访问后就会将第(5)种cookie提交上去,这就是一种CSRF攻击。
可以接纳以下措施防范防范措施:
✓ 搭建HTTPS协议安全网站,cookie不要设置为 sameSite:none
✓ 短信验证码
注:sameSite: https://blog.csdn.net/qq_36690992/article/details/117965822
 
Ajax跨域请求:CORS

跨域请求服务端必要在响应头添加
 
  1. response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
复制代码
 
浏览器Ajax跨域请求
 
  1. $.ajax({
  2.                 url: "https://app1.domain.com:9043/printCookie",
  3.                 contentType: 'application/x-www-form-urlencoded',
  4.                 type: 'POST',
  5.                 async: false,
  6.                 xhrFields: {
  7.                     withCredentials: true
  8.                 },
  9.                 success: function (result) {
  10.                     console.log(result);;
  11.                 },
  12.                 error: function (data) {
  13.                     console.log(data);
  14.                 }
  15.             });
复制代码
 
Ajax请求默认是不会传任何cookie的。加上代码第6、7行参数配置,才开启了浏览器上传cookie,同时服务端配置响应头
 
  1. response.setHeader("Access-Control-Allow-Credentials", "true");
复制代码
 
参考:https://blog.csdn.net/qq_33479841/article/details/123364237
 
二、不同根域下CAS单点登录

基于浏览器的安全机制, 不同的域名之间无法实现cookie共享。针对这种环境要实现单点登录,必要借鉴CAS(Central Authentication Service)的设计思想。CAS的设计思路重要如下图所示:
[img=604.7333333333333,280.07601049868765]https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDI0LmNuYmxvZ3MuY29tL2Jsb2cvMjk3NzI1LzIwMjYwOC8yOTc3MjUtMjAyNjA4MTQxNjA2NTI1OTAtMTQ4Nzc0ODM1Ny5wbmc=[/img]

 
[img=604.7333333333333,993.1393175853019]https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDI0LmNuYmxvZ3MuY29tL2Jsb2cvMjk3NzI1LzIwMjYwOC8yOTc3MjUtMjAyNjA4MTQxNjA2NTM0MTItNTMxMDY4MjkucG5n[/img]

图 CAS时序图 https://apereo.github.io/cas/6.6.x/protocol/CAS-Protocol.html
 
示例:阿里云sso路径
 
  1. https://login.alibaba-inc.com/ssoLogin.htm?
  2. BACK_URL=https%3A%2F%2Fmail.alibaba-inc.com%2Falimail%2F
  3. &preLoginKey=gQksImpGUd1666162247475pCPJHRnhCV
  4. &CONTEXT_PATH=%2Falimail%2F
  5. &APP_NAME=webmail
复制代码
 
 
 
三、基于oauth2的认证

Oauth2是一种授权框架/协议,用来授权给第三方应用,获取用户数据(在不知道用户名、密码的前提下)。用于APP或网页应用微信登录、 QQ 登录、微博登录。第三方网站上授权获得用户信息之后,进行绑定等操作。
 
OAuth2.0 协议的授权流程可以参考下面的流程图,共四个角色,其中 Client 指第三方应用,Resource Owner 指用户,Authorization Server 是开放平台的授权服务器,Resource Server 是开放平台的 API 服务器(用户数据)。
[img=604.733,317.504]https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDI0LmNuYmxvZ3MuY29tL2Jsb2cvMjk3NzI1LzIwMjYwOC8yOTc3MjUtMjAyNjA4MTQxNjA2NTI0NTktMTI3NjY3MzM4OS5wbmc=[/img]

图 抽象协议流
 
[img=604.733,561.479]https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDI0LmNuYmxvZ3MuY29tL2Jsb2cvMjk3NzI1LzIwMjYwOC8yOTc3MjUtMjAyNjA4MTQxNjA2NTI1ODMtNzk4OTA1NjA0LnBuZw==[/img]

图 获取token及认证过程
 
强调local state的概念,这个字段是在登录成功后获取Authorization Code时传给AS的,是什么作用呢?
[img=604.733,413.424]https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDI0LmNuYmxvZ3MuY29tL2Jsb2cvMjk3NzI1LzIwMjYwOC8yOTc3MjUtMjAyNjA4MTQxNjA2NTI3NzktNTQ4ODgwNDEucG5n[/img]

以绑定两个账号为例:攻击者A获取自己的Authorization Code,制造跳转毗连到APP服务,用户B在不知情的环境下,在自己浏览器上使用该毗连发起了绑定请求(GET方式),最终绑定了A的账号。
 
  1. 要防止这样的攻击其实很容易,作为第三方应用的开发者,只需在OAuth认证过程中加入state参数,并验证它的参数值即可。具体细节如下:
  2.  
  3.     在将用户重定向到OAuth2的Authorization Endpoint去的时候,为用户生成一个随机的字符串,并作为state参数加入到URL中。
  4.     在收到OAuth2服务提供者返回的Authorization Code请求的时候,验证接收到的state参数值。如果是正确合法的请求,那么此时接受到的参数值应该和上一步提到的为该用户生成的state参数值完全一致,否则就是异常请求。
  5.     state参数值需要具备下面几个特性:
  6.     1.不可预测性:足够的随机,使得攻击者难以猜到正确的参数值
  7.     2.关联性:state参数值和当前用户会话(user session)是相互关联的
  8.     3.唯一性:每个用户,甚至每次请求生成的state参数值都是唯一的
  9.     4.时效性:state参数一旦被使用则立即失效
  10.  
  11. 链接:https://www.jianshu.com/p/c7c8f51713b6
  12.  
复制代码
 
 
OAuth考虑了各种Web攻击,比如CSRF (Cross-Site Request Forgery), Clickjacking等,OAuth协议文档中已经有了比较全面的阐述
参考:https://www.rfc-editor.org/rfc/rfc6749
https://www.jianshu.com/p/c7c8f51713b6
 
四、CAS与OAuth2区别:

● CAS 客户端要获取的最终信息是,这个用户到底有没有权限访问我(CAS 客户端)的资源;
● OAuth2 获取的最终信息是,我(oauth2 服务提供方)的用户的资源到底能不能让你(oauth2 的客户端)访问。 存在资源的转移使用。
● CAS感觉就是把oauth2的Client和RS合并到了一起(很微妙也很关键的区别)。
总结:CAS是"直接认证",OAuth2是"授权访问",前者更简单直接,后者更灵活安全。
 
思考:
如何登出
 
附:
实现SSO常见的几个协议:CAS, SAML、OpenID, OAuth2(开放授权)
一些开源框架:
Apereo CAS https://www.apereo.org/projects/cas
keycloak https://www.keycloak.org/
云平台:
阿里云SSO https://help.aliyun.com/document_detail/93684.html
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表