参考项目:
整体流程
-
应用1登录时,客户端拦截器判定到用户并未登录(或登录失效)的情况下,会将URL重定向到:sso-server-url/login?directUrl=client-web-url
-
用户在服务端利用用户名密码等方式完成登录后,服务端大体会做3个事情:
- 根据用户的id在持久化库(比如redis)中绑定当前id对应的具体用户信息,避免每次查询。
- 根据上述的
URL
中的directUrl
进行跳转,并在URL
上带上sessionId
,跳转URL:client-url?sessionId=123
。
- 将这个sessinId保存在服务端自身的cookie中,用来保留当前已经登录的用户的状态
-
用户端解析URL上的sessionId
,判定读取是否已经登录成功,如果登录成功,那么将URL的非持久化的session转为cookie
-
当应用2登录时,拦截器判定本地没有cookie,那么跳转到server,server检测到本地的cookie有上次登录的凭证,那么直接赋值给sessionId然后重定向回1
设计
分为2个部分,server部分和client部分。
server端
server部分的核心设计是:
- 接收客户端传递过来的URL:
?redirectUrl=xxx
- 然后在login页面进行登录,登录完成后根据请求过来的URL上的
redirectUrl
进行回调,同时带上sessionId。
- 同时将这个登录凭证保存到自己的cookie中
- 其他客户端跳转到服务端的时候,检测到这个cookie,那么直接返回并退出
对外提供的接口部分有4个HTTP接口:
/
状态判定,如果没有登录,那么跳转到登录接口。如果已经登录,那么展示用户信息。
/login
客户端如果没有登录,那么会被拦截器重定向到该接口【后续解读】
/doLogin
登录接口
/loginout
退出登录接口
client端
client部分的核心设计是拦截器,该拦截器做如下事情
- 先从Cookie中获取用户的登陆key,如果存在那么从Redis中获取用户信息。
- 当无法从Cookie中获取到登陆key时,会检测URL上是否有sessionKey,如果有那么会根据其获取用户信息,当获取到用户信息后会将SessionId转为Cookie。
简单而言,优先从cookie中获取,找不到采用sessinId获取。
整理
- 因为不同的web对应的url不同,当出现跨域的时候,cookie是无法共享的,不过可以通过url进行明文共享
- Client先从Cookie中获取,然后再考虑从SessinId中获取,该SessionId是Server重定向的时候,发送过来的
流程图
骐骥一跃,不能十步。驽马十驾,功在不舍。