一.前言
优化上一章节讲解了Sso原理,这一节只讲代码的实现。涉及到sso的单点登录一般需要处理4块业务逻辑:
- 单点登录
就是通过sso服务端进行登录的操作。 - 票据验证
将传递到客户端的票据拿到服务端进行验证。 - 授权验证
当在sso服务登录成功后访问别的项目无需在次登录的操作。 - 单点退出
当一个sso客户端退出后其他的sso客户端也需要统一退出的操作。
二.单点登录
2.1 业务流程图
2.2 业务说明
- 我们sso客户端访问需要登录的url 或者登录的url 直接跳转到sso服务端的登录页面(如果已经登录则直接跳转到访问的url)
- 直接访问登录的url,sso客户端的拦截器会将其直接重定向到 sso服务端的登录页面并携带sso客户端访问地址。
- 访问sso客户端需要登录的url(没有登录的情况下)会重定向到sso服务端单点授权验证逻辑中。如果该用户未登录则重定向到 sso服务端的登录页面并携带sso客户端访问地址。
- 输入用户名和密码在sso服务端进行登录,如果用户名和密码错误则重新跳转到登陆页面并提示错误信息。
- 如果用户名和密码正确,则生成 GrantingTicket 并将GrantingTicket 的id 放入cookie中。然后生成 ServiceTicket 并将ServiceTicket 放入GrantingTicket 的缓存map中。
- 将生成 GrantingTicket放入到缓存中(key:GrantingTicket的id value:GrantingTicket)然后再将ServiceTicket 的id 和对应的GrantingTicket的id放入缓存中。
- 重定向到sso客户端 并将 ServiceTicket 的id(ticket)拼接到重新向的url中。
- sso客户端根据ticket 再次调用sso服务端去获取用户信息。
- sso服务端接受到sso客户端 传来ticket后, 根据ticket 获取缓存中的 GrantingTicket的 id,然后再根据GrantingTicket的id 获取GrantingTicket。然后再从GrantingTicket获取用户信息返回给 sso客户端。
- sso客户端接受到用户信息后将其保存在session中。然后再将ticket 和session的关系存入sso客户端 缓存的map中。
- 如果sso客户端根据ticket 获取用户失败则返回sso服务端的登录页面并提示非法操作。
三.票据验证
3.1 业务流程图
3.2 业务说明
- 我们sso客户端访问需要登录的url 或者登录的url 直接跳转到sso服务端的登录页面(如果已经登录则直接跳转到访问的url)
- 直接访问登录的url,sso客户端的拦截器会将其直接重定向到 sso服务端的登录页面并携带sso客户端访问地址。
- 访问sso客户端需要登录的url(没有登录的情况下)会重定向到sso服务端单点授权验证逻辑中。如果该用户未登录则重定向到 sso服务端的登录页面并携带sso客户端访问地址。
- 输入用户名和密码在sso服务端进行登录,如果用户名和密码错误则重新跳转到登陆页面并提示错误信息。
- 如果用户名和密码正确,则生成 GrantingTicket 并将GrantingTicket 的id 放入cookie中。然后生成 ServiceTicket 并将ServiceTicket 放入GrantingTicket 的缓存map中。
- 将生成 GrantingTicket放入到缓存中(key:GrantingTicket的id value:GrantingTicket)然后再将ServiceTicket 的id 和对应的GrantingTicket的id放入缓存中。
- 重定向到sso客户端 并将 ServiceTicket 的id(ticket)拼接到重新向的url中。
- sso客户端根据ticket 再次调用sso服务端去获取用户信息。
- sso服务端接受到sso客户端 传来ticket后, 根据ticket 获取缓存中的 GrantingTicket的 id,如果id存在则票据验证成功,然后再根据GrantingTicket的id 获取GrantingTicket。然后再从GrantingTicket获取用户信息返回给 sso客户端。如果不存在则返回错误信息,跳转到Sso服务端登录界面。
四.授权验证
4.1 业务流程图
4.2 业务说明
- 当我们访问需要登录url时并且用户session信息为null的情况下 则走单点授权验证。
- 如果该用户未登录则重定向到 sso服务端的登录页面并携带sso客户端访问地址。后面的就走sso单点登录操作。
- 如果该用户已经在别的系统已经登录过。sso客户端拦截器拦截到该操作是单点授权验证后会重定向到sso服务端单点授权url。
- sso服务端拦截器拦截到 单点授权url后 首先获取 cookie中 GrantingTicket的id 。然后根据GrantingTicket的id获取缓存中的GrantingTicket。
- sso服务端 生成ServiceTicket 并放入到GrantingTicket的缓存中。
- sso服务端 重定向到sso客户端并携带ServiceTicket 的id (ticket)。
- sso客户端拦截器拦截到重定向url并获取到ticket 。然后根据ticket从sso服务端获取用户的信息。
- sso服务端接受到sso客户端ticket 根据ticket 获取缓存中的 GrantingTicket的id,然后再根据GrantingTicket的id 获取GrantingTicket。然后再从GrantingTicket获取用户信息,返回给客户端。
- sso客户端接受到用户的信息后 将信息保存在session中
- 然后将 ticket 和session的关系对应保存在缓存中。
五.单点退出
5.1 业务流程图
5.2 业务说明
- sso客户端点击退出按钮,会向sso服务端发起退出登录操作。
- sso服务端拦截器拦截到退出的操作后会将进入退出的操作逻辑
- sso服务端 第一步先获取sso服务端在存储的GrantingTicket的cookie信息
- 根据在cookie中存储的GrantingTicket的id 从缓存中获取到GrantingTicket。
- 然后将sso服务端在存储的GrantingTicket的cookie信息清除。
- 获取GrantingTicket 缓存的ServiceTicket缓存map信息。
- 遍历ServiceTicket的Map信息。
- 通过ServiceTicket的host信息依次调用客户端的退出url并携带ticket。
- sso客户端拦截器拦截到退出的操作并获取到ticket.根据之前在客户端缓存的map中根据ticket获取到sesion的信息并调用sess.invalidate();
- sso服务端重定向到sso服务端的登录页面。
六.代码实现
至此,Sso第一次实现结束,后期的优化方向是:
- Sso的跨域请求
- 用户登录的真实模拟,集成数据库。
- 集成Redis票据的存储方式利用缓存实现。
- 拓展Sso的业务场景。