单点登录(三)—— 单点登出原理手写实现

单点登出原理


我们想实现单点登出,首先会想到在当前应用下把Session销毁即可,但是仔细一想,这样的话,是不能实现把与之共享一个token的应用的Session销毁,这条路不行。

那既然所有的应用登录都需要通过一个验证服务端,那么注销的时候也通过该服务端,向所有客户端发送注销请求即可实现
单点登录(三)—— 单点登出原理手写实现_第1张图片

代码实现


根据原理图,我们想让服务端(sso-server)保存用户的token在登录的时候已经实现,但现在还需要保存登出地址(客户端地址),用户的session(sessionid),因此我们可以通过一个对象来保存这两个信息,如下在服务端创建一个ClientInfoVo对象

@Data
public class ClientInfoVo {
    private String clientUrl;
    private String jsessionid;
}

有了对象,还需要将其保存到模拟的数据库中,因此在上一篇中的MockDB中添加一个数据结构,如下
单点登录(三)—— 单点登出原理手写实现_第2张图片
当我们第一次登录时,需要到/verify判断token是否有效,因此,我们可以在校验token成功情况下将clientUrljsessionid存到模拟数据库中,而首先,需要将两者信息携带过去
单点登录(三)—— 单点登出原理手写实现_第3张图片
接下来就是在校验token成功时将携带过来的信息保存到模拟数据库中,如下
单点登录(三)—— 单点登出原理手写实现_第4张图片
至此,完成了携带登出信息并保存的过程

当我们点击注销按钮时,应该到服务端进行销毁session并通过服务端向所有客户端发起请求销毁客户端session,这就需要我们在登录的时候就把登出地址(服务端登出请求)携带,如下在客户端登录时携带上了服务端登出地址
单点登录(三)—— 单点登出原理手写实现_第5张图片
其中获取登出地址的工具类如下,即服务端和客户端地址加上/logOut请求
单点登录(三)—— 单点登出原理手写实现_第6张图片
现在当我们点击注销时,就对到服务端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.MySessionListenerlistener-class>
listener>

既然服务端要遍历通知所有客户端销毁session,那么所有客户端也需要销毁session的方法
单点登录(三)—— 单点登出原理手写实现_第7张图片
至此,已经完成了单点登出。

你可能感兴趣的:(单点登录)