溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Spring Session Redis 在不同服務(wù)間共享 Session 時的類共享方案的示例分析

發(fā)布時間:2021-09-10 13:42:37 來源:億速云 閱讀:241 作者:柒染 欄目:大數(shù)據(jù)

今天就跟大家聊聊有關(guān)Spring Session Redis 在不同服務(wù)間共享 Session 時的類共享方案的示例分析,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

Spring Session Redis 是不安全的

當(dāng)在多服務(wù)之間使用 Spring Session Redis 進(jìn)行 Session 共享要非常小心,因為它很不安全,很有可能導(dǎo)致整個服務(wù)實例不可用,無法處理任何請求。其中比較危險的地方就是在進(jìn)行序列化,反序列化的時候(這種類型的錯誤尤其容易在沒有開發(fā)規(guī)范的團(tuán)隊內(nèi)發(fā)生,就是什么樣的數(shù)據(jù)可以往共享存儲里面存,什么樣的不能存。存的時候要以什么樣的格式去存,這些都要有規(guī)定才比較安全。因為共享存儲是會影響到別人的不僅僅是為了自己的服務(wù)用起來方便)。RedisSerializer 接口的實現(xiàn)都是在序列化和反序列化出錯的時候直接拋出異常從而導(dǎo)致整個請求錯誤。

public interface RedisSerializer<T> {

	/**
	 * Serialize the given object to binary data.
	 * 
	 * @param t object to serialize
	 * @return the equivalent binary data
	 */
	byte[] serialize(T t) throws SerializationException;

	/**
	 * Deserialize an object from the given binary data.
	 * 
	 * @param bytes object binary representation
	 * @return the equivalent object instance
	 */
	T deserialize(byte[] bytes) throws SerializationException;
}

下面用一張圖來說明我遇到的問題。Spring Session 的誕生老實說并不是為了分布式系統(tǒng),而是為集群系統(tǒng)提供了一種 Session 解決方案。但是我們把 Spring Session 用在了分布式系統(tǒng)上用以解決 Session 共享的問題老實說本身就是有點難為人家 Spring Session 了 。

Spring Session Redis 在不同服務(wù)間共享 Session 時的類共享方案的示例分析

Spring Session 實現(xiàn) Session 共享的大致原理

Spring Session 實現(xiàn) Session 共享的大致原理如下圖所示 , 使用一個 Filter 來攔截所有請求,在攔截到請求之后對 HttpServletRequest 和 HttpServletResponse 進(jìn)行包裝 (HttpServletRequestWrapper  , HttpServletResponseWrapper)。在包裝中對 session 進(jìn)行控制 ,將 session 數(shù)據(jù)都存儲在第三方存儲當(dāng)中。

Spring Session Redis 在不同服務(wù)間共享 Session 時的類共享方案的示例分析

Spring Session Redis 在不同服務(wù)間共享 Session 時的類共享方案

在了解了 Spring Session 的工作原理后再去考慮這個問題就有頭緒了 。還是通過圖形的方式來做大概的說明。

Spring Session Redis 在不同服務(wù)間共享 Session 時的類共享方案的示例分析

學(xué)習(xí) Spring Session 的 SessionRepositoryFilter 的實現(xiàn)方式 , 添加一個 Filter 順序在 SessionRepositoryFilter 之后 , 在攔截過程中包裝 HttpServletRequest , 重寫 getSession(boolean create)  和 getSession() 方法, 自定義一個 SafetyHttpSessionWrapper 包裝 Session ,重寫 setAttribute(String name , Object value) 函數(shù) , 在保存屬性成功后利用 redis 的發(fā)布訂閱機制發(fā)送消息到 redis , 消息的內(nèi)容為所保存對象的 .class 文件數(shù)據(jù)。在消息訂閱端 , 接收到消息后利用 javassist 和 net.bytebuddy.dynamic.loading.ByteArrayClassLoader 將 .class 文件數(shù)據(jù)加載轉(zhuǎn)換成 Class 的實例對象,但是這個  Class 實例的范圍被限定在 ByteArrayClassLoader 中 , 而這個 ByteArrayClassLoader 是提供給 RedisSerializer 內(nèi)部使用的 , 比如 JdkSerializationRedisSerializer , GenericJackson2JsonRedisSerializer 都需要使用到 ClassLoader 。這樣當(dāng) 服務(wù)A 在存儲任何自定義的對象在 Session 中時, 訪問服務(wù) B 也不會出現(xiàn)讀取 Session 反序列化 ClassNotFoundException 的錯誤了。

看完上述內(nèi)容,你們對Spring Session Redis 在不同服務(wù)間共享 Session 時的類共享方案的示例分析有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI