[sso] 单点登录认证流程
一、流程说明
第一步:访问cas过滤链接ssoLogin,拼凑定向到 CAS_SERVER 获取ticket的URL
第二步:CAS_SERVER校验用户信息,生成Ticket
第三步:重新定向到访问客户端的ssoLogin并附加Ticket参数和值
第四步:根据传来的Ticket拼凑定向到CAS_SERVER的连接去校验Ticket的合法性
第五步:CAS_SERVER校验成功后,会返回XML报文并重新定向到访问客户端的ssoLogin
解析该XML报文,构造用户信息对象存储在session中
然后根据ssoLogin设置的loginSuccessUrl跳转到登录成功后的访问页面
二、具体步骤
1、导入所需依赖jar包
2、在web.xml中配置需要单点登录过滤的路径为/ssoLogin
本地客户端URL:http://localhost:8080/webtest/ssoLogin
远程cas服务器地址CAS_LOGIN_URL:https://192.168.6.100/ptyhzx-sso/login
web.xml配置
ssoclient.properties配置
3、流程剖析
(1) 访问ssoLogin[处理类:SSOServlet]带上用户名和密码 - requestUrl
https://localhost:8080/webtest/ssoLogin?username=user1&password=123456
(2) 构造第一次访问CAS_SERVER的getTicketURL
getTicketURL = CAS_LOGIN_URL ? SERVICE参数
目的:获取TICKET
http://192.168.6.100/ptyhzx-sso/login?service=http%3A%2F%2Flocalhost%3A8080%2Fwebtest%2FssoLogin%3Frenew=true&other=form&accessToken=C45BD9AE005909FE2F9EC45D54FF70D2ADD106142B17461AEC94AD4A098A7420025D7694680916B5276CDDE8FA085C5A
说明:
后台根据 requestUrl 构造 service 参数
service的值 = 去掉用户名密码后的requestUrl参数 + renew参数 + other参数 + 用户名密码加密后的accessToken
拼接完毕后再对service整体编码作为最终的service值
构造获取getTicektURL完毕后立刻重定向到该URL去
(3) CAS_SERVER根据accessToken验证用户信息
验证成功
1、生成TOKEN【示例:ST-5649-Wv3HsI75tG7dNzEu9Uxg-cas01.example.org】
2、重定向到requestURL,此时requestURL中包含了ticket参数
http://localhost:8080/webtest/ssoLogin;jsessionid=DBFC81A7ECA2C24C90B2AB5440475E05&ticket=ST-5649-Wv3HsI75tG7dNzEu9Uxg-cas01.example.org
验证失败,跳转到配置的loginFailureURL并提示具体错误信息
(4) 根据得到的ticket调用验证方法:
Assertion vaildAssertion = ticketValidator.validate(ticket,requestURL);
调用validate方法会构造验证的 validURL 去CAS服务器验证这个TICKET是否合法
validateURL =
CAS_SERVER_URL/serviceValidate? + ticket参数 + serviceCode参数 + service参数
service参数是验证成功后重定向的URL地址
http://192.168.6.100/ptyhzx-sso/serviceValidate?ticket=ST-5653-dURt1ErNHUuEm9j3vsqe-cas01.example.org&serverCode=101&service=http%3A%2F%2Flocalhost%3A8080%2Fwebtest%2FssoLogin
String serverResponse = retrieveResponseFromServer(new URL(validationUrl), ticket);
(6)验证成功后cas_server会返回xml报文到重定向的URL地址
<!-- 成功时 --> <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'> <cas:authenticationSuccess> <cas:user>a1</cas:user> <cas:attributes> <cas:id>1100000000000000000</cas:id> <cas:sex>1</cas:sex> <cas:username></cas:username> <cas:authenticationMethod>com.jeaw.sso.adaptors.jdbc.QueryDatabaseAuthenticationHandler</cas:authenticationMethod> <cas:email></cas:email> <cas:nickname>a1</cas:nickname> <cas:status>1</cas:status> <cas:cellphone></cas:cellphone> <cas:usertype>03</cas:usertype> <cas:loginid>1000000001</cas:loginid> <cas:password>111111</cas:password> </cas:attributes> </cas:authenticationSuccess> </cas:serviceResponse> <!-- 失败时 --> <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'> <cas:authenticationFailure code='INVALID_TICKET'> 未能够识别出目标 'ST-136-Tnw7BLEKurYGcDaZFgo6-cas01.example.org'票根 </cas:authenticationFailure> </cas:serviceResponse>
(7) 后续操作
1、调用parseResponseFromServer(serverResponse)解析该报文以生成 Assertion 对象
vaildAssertion
2、构造用户信息对象存于session
request.getSession().setAttribute("userInfo",vaildAssertion);
3、跳转到登陆成功页面
response.sendRedirect(loginSuccessUrl);
(8) 交互流程一览
(9)参考文档
基于CAS实现单点登录(SSO):登录成功后,cas client如何返回更多用户信息