SSO单点登录(Single Sign On)

前言

本文以"cookie-based" sso为例, 结合"redis"讲述sso过程, 也可考虑"jwt"等其他方式来实现sso

1.几个基本概念

单点登录方案涉及到好多方面:
改host
安装证书
配置HTTPS。

https!!!
https!!!
https!!!

1.1 什么是跨域Web SSO

域名通过“.”号切分后,从右往左看,不包含“.”的是顶级域名,
包含一个“.”的是一级域名,包含两个“.”的是二级域名,以此类推。

例如对网址'http://www.baidu.com/a.jpg',域名部分是'www.baidu.com'。
用“.”拆分后从右往左看:

'com'不包含“.”,是顶级域名; 
'baidu.com'包含一个“.”,是一级域名;
'www.baidu.com'包含两个“.”,是二级域名。

基于cookie的SSO主要需要解决的问题是:Cookie是不能跨域传递的,
如何将一个域的Cookie通知给其它应用(不在同一个域)?

Cookie domain

为了让Http协议在一定程度上保持上下文,server在响应的头部可以加入Set-Cookie来写入一些数据到客户端,
Set-Cookie中的domain字段用来表示这个cookie所在的域。
比如:
我们访问www.baidu.com,如果server在返回头部中加入了Set-Cookie,如果不指定domain,
那么默认这个cookie的域就是www.baidu.com,也就是只有访问www.baidu.com时客户端才会把这个cookie返给服务端。

如果我们指定domain为.baidu.com,那么客户端在访问以下域名:
www.baidu.com www1.baidu.com a.baidu.com ***.baidu.com 时都能够把cookie返回。

所以,我们得出一条结论:
客户端对cookie的domain的匹配是从结尾进行匹配的,有了这个基础,我们就可以实现我们的SSO登陆了。

1.2 浏览器读写cookie的安全性限制:一级或顶级域名不同的网站,无法读到彼此写的cookie

>> baidu.com无法读到alibaba.com写的cookie。

>> 一级域名相同,只是二级或更高级域名不同的站点,可以通过设置domain参数共享cookie读写。
这种场景可以选择不跨域的SSO方案。

>> 域名相同,只是https和http协议不同的URL,默认cookie可以共享。

1.3 http协议是无状态协议。浏览器访问服务器时,要让服务器知道你是谁,只有两种方式

>> 方式一:
把“你是谁”写入cookie。它会随每次HTTP请求带到服务端;

>> 方式二:
在URL、表单数据中带上你的用户信息(也可能在HTTP头部)。
这种方式依赖于从特定的网页入口进入,因为只有走特定的入口,
才有机会拼装出相应的信息,提交到服务端。

大部分SSO需求都希望不依赖特定的网页入口(集成门户除外),所以后一种方式有局限性。
适应性强的方式是第一种,即在浏览器通过cookie保存用户信息相关凭据,随每次请求传递到服务端。

1.4 SSO单点登录核心流程

>> 1 用户未登录时访问子站一,子站一服务器检测到用户没登录(没有本站session,因为没传过来session对应cookie), 
于是通知浏览器重定向到SSO服务站点,并在跳转的URL参数中带上当前页面地址,以便登录后自动跳转回本页。

>> 2  SSO服务站点检测到用户没有登录,于是显示登录界面。
用户提交登录请求到服务端,服务端验证通过,创建和账号对应的用户登录凭据(token), 
将token作为Key, userInfo(去除敏感信息)加密存储进redis中。
然后,服务端通知浏览器把该token作为SSO服务站点的cookie存储起来,
并重定向回子站一,跳回子站一的URL参数中会带上这个token。

>> 3  浏览器在写SSO服务站点cookie后,跳转回子站一
子站一服务端检测到浏览器请求的URL中带了单点登录的token,于是把这个token发到SSO服务站点验证。
SSO服务端站点拿token解密出用户账号,把账号信息中允许子站一访问的部分返回给子站一。
子站一根据返回的信息生成用户在本站的会话,把会话对应cookie写入浏览器,从而完成在本站的登入以及会话保持。
之后用户访问再子站一时,都会带上这个cookie,从而保持在本站的登录状态。

>> 4  用户再访问子站二
子站二服务器检测到用户没登录,于是通知浏览器跳转到SSO服务站点。

>> 5  浏览器访问SSO服务站点时会带上上述步骤2创建的token这个cookie
SSO服务站点根据该token去redis中能找到对应用户,于是通知浏览器跳转回子站二,并在跳转回去的URL参数中带上这个token。

>> 6  子站二服务端检测到浏览器请求的URL中带上了单点登录的token,于是又会走步骤3,完成用户在本站的自动登录。
HTTP设置cookie时,提供了2个属性,可以增强cookie的安全性,分别是secure属性和httpOnly属性。

secure属性可防止信息在传递的过程中被监听捕获后导致信息泄露,
如果设置为true,可以限制只有通过https访问时,才会将浏览器保存的cookie传递到服务端,
如果通过http访问,不会传递cookie。

httpOnly属性可以防止程序获取cookie,如果设置为true,通过js等将无法读取到cookie,能有效的防止XSS攻击。

当domain为:*.abc.com.cn 
a.abc.com.cn 和b.abc.com.cn要想获取前端传递的cookie,要注意一下secure 和httpOnly的值
SSO单点登录(Single Sign On)_第1张图片
SSO登录.png
SSO单点登录(Single Sign On)_第2张图片
SSO的cookie属性设置.png

如果cookie被禁用了怎么办???(截至20190724)

这里给出当前日期20190724时, 阿里巴巴, 百度, 网易, 博客园的相关处理方案(PC端)

#一般App端多采用非cookie的token方式:
将服务端生成的安全随机token保存至客户端的localStorage或者sessionStorage中, 
然后客户端每次请求的时候在header中或者url后携带上该token。

"App端参考链接"
https://www.jianshu.com/p/e41a329ef353

SSO单点登录(Single Sign On)_第3张图片
禁用cookie时--阿里巴巴的方案--登录前.png
SSO单点登录(Single Sign On)_第4张图片
禁用cookie时--阿里巴巴的方案--强行登录后.png
SSO单点登录(Single Sign On)_第5张图片
禁用cookie时--百度的方案.png
SSO单点登录(Single Sign On)_第6张图片
禁用cookie时--网易的方案.png
SSO单点登录(Single Sign On)_第7张图片
禁用cookie时--博客园的方案.png

summary

总结一下单点登录要做的事情:
>> 单点登录(SSO系统)是保障各业务系统的用户资源的安全 。
>> 各个业务系统获得的信息是,这个用户能不能访问我的资源。
>> 单点登录,资源都在各个业务系统这边,不在SSO那一方。 
用户在给SSO服务器提供了用户名密码后,作为业务系统并不知道这件事。 
>> SSO给业务系统一个随机的安全的加密过的token,那么业务系统是不能确定这个token是用户伪造的,还是真的有效,
所以要拿着这个ST去SSO服务器再问一下,这个用户给我的ST是否有效,是有效的我才能让这个用户访问。

https://www.cnblogs.com/cjsblog/p/9277677.html
https://blog.csdn.net/qq_38401919/article/details/80535258
https://ken.io/note/sso-design-implement
https://www.jianshu.com/p/33e6be06617f

你可能感兴趣的:(SSO单点登录(Single Sign On))