天天看點

單點登入(三)—— 單點登出原理手寫實作

單點登出原理

我們想實作單點登出,首先會想到在目前應用下把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的方法

單點登入(三)—— 單點登出原理手寫實作

至此,已經完成了單點登出。

繼續閱讀