单点登录解决方案
共享 Session
@startuml
actor User order 1
participant Browser order 2
participant "SSO Server" order 3
participant App1 order 4
participant App2 order 5
database Redis order 6
== 第一次访问 App1 ==
User -> Browser: 访问 App1
activate Browser
Browser -> App1: GET https://app1.example.com/
activate App1
return 302 Location: https://sso.example.com/login?\nservice=https%3A%2F%2Fapp1.example.com%2F
activate Browser
Browser -> "SSO Server": GET https://sso.example.com/login?\nservice=https%3A%2F%2Fapp1.example.com%2F
activate "SSO Server"
return SSO 登录表单
Browser -> User: 展示 SSO 登录表单
activate User
return: 提交 SSO 登录表单
Browser -> "SSO Server": POST https://sso.example.com/login?\nservice=https%3A%2F%2Fapp1.example.com%2F
activate "SSO Server"
"SSO Server" -> "SSO Server": 认证用户
"SSO Server" -> Redis: set sso:ABC1234567 {"username": "Tom"}
activate Redis
return ok
return Set-Cookie: JSESSIONID=ABC1234567; Domain=example.com\n302 Location: https://app1.example.com/
deactivate Browser
Browser -> App1: Cookie: JSESSIONID=ABC1234567\nGET https://app1.example.com/
activate App1
App1 -> Redis: get sso:ABC1234567
activate Redis
return {"username": "Tom"}
return 200 [https://app1.example.com/]
return 展示 App1
== 第二次访问 App1 ==
User -> Browser: 访问 App1
activate Browser
Browser -> App1: Cookie: JSESSIONID=ABC1234567\nGET https://app1.example.com/resource/
activate App1
App1 -> Redis: get sso:ABC1234567
activate Redis
return {"username": "Tom"}
return 200 [https://app1.example.com/resource/]
return 展示 App1
== 第一次访问 App2 ==
User -> Browser: 访问 App2
activate Browser
Browser -> App2: Cookie: JSESSIONID=ABC1234567\nGET https://app2.example.com/
activate App2
App2 -> Redis: get sso:ABC1234567
activate Redis
return {"username": "Tom"}
return 200 [https://app2.example.com/]
return 展示 App2
@enduml优点:
实现单点登出比较简单
缺点:
不支持跨顶级域名登录
严重依赖外部系统(Redis)
JSON Web Token (JWT)
优点:
服务端无状态
缺点:
不支持跨顶级域名登录
实现单点登出(失效 Token)比较复杂
续签 Token 比较复杂
需要额外的计算成本
Central Authentication Service (CAS)
优点:
支持跨顶级域名登录
缺点
实现单点登出比较复杂
最后更新于