单点登出原理
我们想实现单点登出,首先会想到在当前应用下把Session销毁即可,但是仔细一想,这样的话,是不能实现把与之共享一个token的应用的Session销毁,这条路不行。
那既然所有的应用登录都需要通过一个验证服务端,那么注销的时候也通过该服务端,向所有客户端发送注销请求即可实现

代码实现
根据原理图,我们想让服务端(sso-server)保存用户的token在登录的时候已经实现,但现在还需要保存登出地址(客户端地址),用户的session(sessionid),因此我们可以通过一个对象来保存这两个信息,如下在服务端创建一个ClientInfoVo对象
@Data
public class ClientInfoVo {
private String clientUrl;
private String jsessionid;
}
有了对象,还需要将其保存到模拟的数据库中,因此在上一篇中的MockDB中添加一个数据结构,如下

当我们第一次登录时,需要到/verify判断token是否有效,因此,我们可以在校验token成功情况下将clientUrl和jsessionid存到模拟数据库中,而首先,需要将两者信息携带过去

接下来就是在校验token成功时将携带过来的信息保存到模拟数据库中,如下

至此,完成了携带登出信息并保存的过程
当我们点击注销按钮时,应该到服务端进行销毁session并通过服务端向所有客户端发起请求销毁客户端session,这就需要我们在登录的时候就把登出地址(服务端登出请求)携带,如下在客户端登录时携带上了服务端登出地址

其中获取登出地址的工具类如下,即服务端和客户端地址加上/logOut请求

现在当我们点击注销时,就对到服务端www.sso;8081/logOut请求,到这里销毁服务端session,如下到SsoServerController类中添加如下代码
@RequestMapping("/logOut")
public String logOut(HttpSession session){
session.invalidate();
return "login";
}
服务端session销毁了,我们还需要发起请求让所有客户端的session销毁,这里可以通过服务端的一个session监听器实现,如下
public class MySessionListener implements HttpSessionListener {
//session创建时候执行的操作
public void sessionCreated(HttpSessionEvent se) {
}
//session销毁时候执行的操作
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
String token = (String) session.getAttribute("token");
//销毁表中数据
MockDB.T_TOKEN.remove(token);
List<ClientInfoVo> clientInfoVos = MockDB.T_CLIENT_INFO.remove(token);
//遍历让验证服务端通知所有客户端销毁session
for (ClientInfoVo infoVo : clientInfoVos) {
try {
HttpUtil.sendHttpRequest(infoVo.getClientUrl(),infoVo.getJsessionid());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
并在web.xml中注册监听器
<!--监听器注册-->
<listener>
<listener-class>com.ranran.listener.MySessionListener</listener-class>
</listener>
既然服务端要遍历通知所有客户端销毁session,那么所有客户端也需要销毁session的方法

至此,已经完成了单点登出。
本文深入探讨单点登出的实现原理,介绍如何通过验证服务端统一管理用户登录状态,实现在用户登出时,同步销毁所有相关联应用的Session,确保用户信息的安全性。
—— 单点登出原理手写实现&spm=1001.2101.3001.5002&articleId=104260462&d=1&t=3&u=4330852527f145a2a07188b2587231c3)
4137

被折叠的 条评论
为什么被折叠?



