0
点赞
收藏
分享

微信扫一扫

一个简单的SSO统一登录设计

8052cf60ff5c 2022-02-14 阅读 126

前言

随着公司的发展,公司内部各种系统后台也越来越多,需要进行的登录验证的操作也越来越多。不同的账号体系,不受限制的口令管理也成了一个问题。为了解决这些问题,需要对公司的登录管理进行统一,使用同一套的账号口令体系,并对口令的安全管控进行限制。

于是单点登录的需求就变得很现实。单点登录-Single Sign On,简称SSO。可以理解为:一处登录,处处登录

以我司为例:内部系统的域名为 wwdz.com,设计单点登录的目标是,只要登录了其中的一个系统  a.wwdz.com 再打开其他接入单点登录的系统,比如 b.wwdz.com,可以直接获取用户信息,无需再次输入账号口令


SSO流程

一个简单的SSO统一登录设计_统一登录

具体步骤:假定都是第一次访问:

1 用户通过浏览器访问 http://A.wwdz.com/some/page

2 浏览器向系统A发送请求

3 这是第一次访问系统A,系统A没有检测到用户的登录状态(cookie session等找不到)。认为其没有登录。此时A系统发起一个浏览器重定向,让浏览器跳转到统一登录并将redirectUrl参数设定为用户访问A系统时url,形如:​​http://sso.wwdz.com/login?redirectUrl=http://A.wwdz.com/some/page​​

4 浏览器接收到A系统的302跳转,访问 http://sso.wwdz.com/login?redirectUrl=http://A.wwdz.com/some/page

5 这是第一次访问SSO,同样的SSO没有检测到用户的登录状态,此时依照浏览器请求,返回SSO的login页面(页面是一个简单的表单,用于提交用户账号与口令)。

6 用户根据页面提示输入账号口令,并提交。

7 SSO接收数据进行校验:    用户账号口令校验不通过,不允许登录    用户账号口令校验通过,则:

  • 为其在SSO服务端创建session

  • 签发token(JWT格式),并在payload中指定过期时间等信息。

  • 通知浏览器进行重定向,目标是系统A,并把token作为url参数进行传递 或者 将token写入 cookie中(*.wwdz.com Authorization)

8 浏览器获得SSO的302返回,此时的请求中包含token 或者 在cookie中有token的值。

9 浏览器携带token访问A系统。

10 A系统根据请求信息获取token。

11 A系统将token写入Header Authorization中 请求SSO的attach/vaild接口已校验该token是否正确。

12 SSO接收A系统请求,校验token。token可能会出现的问题有:

token过期
用户在使用过程中,口令变化
token无法解码
用户被锁定

如果token有问题,则返回相应错误状态码如果token不符合上述状态,则将用户信息返回给系A统

13 系统A根据SSO返回的信息对用户最初的请求进行处理

14 浏览器对A系统返回页面进行展示。以上在用户第一次登录的情况下的一个流程。

如果用户已经登录了系统A,需要访问系统B,唯一不同的在第5步。按照上文逻辑,登录A系统必然会登录SSO,所以在登录系统B的过程,1-4步骤中的流程不变(只是将请求的Url换成http://B.wwdz.com/some/page),只是在第5步的时候,不再需要SSO返回用户登录页面而是直接根据用户信息生成token并拼装URL重定向给浏览器,就是第8步。其余流程不变。

以上就实现了一个SSO的登录流程。



钉钉扫码登录

但是随着各种口令安全规章制度的完善,我司对用户口令的生命周期与强度都做了一定的要求,这就导致了一个很尴尬的问题:有些同学在设计了一个超复杂的口令后……把自己的口令忘记了。虽然提供重置口令功能,但不能总是在需要用口令的时候重置口令(虽然这个方法会提高口令更新频率,对安全来说是个好办法,但是还是影响工作效率),于是在现有SSO的基础上添加钉钉扫码登录功能

一个简单的SSO统一登录设计_统一登录_02


钉钉扫码登录的逻辑不是很复杂,钉钉提供了很详细的文档对此操作进行了描述。

在钉钉开放平台创建 移动接入应用 并在 登录 中创建 扫码登录应用授权 ,指定相应的回调地址、appId、 appSecret等信息。

在登录页引入钉钉的js文件,并设定回调地址等信息。

用户扫码并在手机上点击确认后,js会将获取的loginTmpCode返回给设定的回调地址

回调服务器获取loginTmpCode后构造相应的url跳转到钉钉服务器

如果钉钉服务器调用成功,则会302跳转到goto参数指定的redirect_uri,并向url参数中追加临时授权码code及state参数。

调用钉钉接口获取授权用户的个人信息。

将钉钉的个人信息与SSO中的信息进行关联实现免口令登录。

一键登录

但是,随着时间的推移,又有同学说扫码登录还是要掏手机,不方便,于是乎萌生了一键登录的想法。

大家在使用QQ的时候可能会注意到:当用户使用QQ客户端之后,在使用浏览器访问腾讯的一些登录页面时,登录页面会获取到QQ信息,登录页面会变成QQ一键登录。实现这样的一键登录就要自己做一个客户端,客户端listen一个本地端口。浏览器在访问统一登录的时候请求这个本地端口以获取用户信息,进而实现一键登录的功能。

但是,这个想法的出现不仅仅是想做一键登录,也是由于VPN客户端安装使用的不方便(这是另一个话题了)。

为了实现这个功能,首先要改造一下SSO登录页面。需要假定一个请求用户信息的本机接口。

默认情况下一键登录是不显示的。但如果这个接口是通的,则隐藏原有的登录界面,直接提示一键登录,并获取从该接口获取相应的用户鉴权信息(username passwd)。以下是添加到SSO登录页中的js代码。

$(document).ready(function(){
document.getElementById('autologin').style.display='none'
$.get("http://127.0.0.1:xxxx",function(data,status){
let datas = data.split(' ')
let username = datas[0]
let passwd = datas[1]
console.log("username = " + username)
console.log("passwd = " + passwd)
document.getElementById('login').style.display='none'
document.getElementById('autologin').style.display=''
document.getElementById('autousername').value=username
document.getElementById('autopasswd').value=passwd
});
});

之后就是创建客户端,具体逻辑可以再写一篇,这里直说一下实现方案。

由于公司里使用MAC和win的都很多,所以搞一套易于扩展的跨平台方案是很必要的。最后我选择了Electron。

在我的理解中,Electron可以看做是用有一定限制的浏览器做GUI的跨平台APP解决方案。

启动了这个客户端app后,它会监听本机的指定端口,一旦被访问就会返回相应账号信息(只有用户登录并开启一键登录之后才会监听),这样就能与改造后的SSO登录页面进行适配,效果如下

客户端效果(由于是内嵌浏览器,基本的界面都是与SSO登录页保持一个风格,vpn客户端功能以后再说)

一个简单的SSO统一登录设计_SSO_03

SSO统一登录在检测到一键登录后的效果

一个简单的SSO统一登录设计_统一登录_04点击一键登录后,页面会自动将鉴权信息发送给SSO,其流程完全没有改变。

The END

一个简单的SSO统一登录设计_SSO_05

举报

相关推荐

0 条评论