網站首頁 編程語言 正文
前言:
本文使用 .NET Core SDK 3.1 的版本。
1) 關于Http中的會話
- Http是一種采用請求響應消息交換模式,且無狀態的傳輸協議。
- 該協議確保客戶端將請求報文發送給目標服務器并接收來自服務端的響應報文,這個報文交換是一個Http事務。
- 從協議的角度講,即使在使用長連接的情況下,同一個客戶端和服務器之間進行多個Http事務也是完全獨立的
- 所以需要在應用層為兩者去建立一個上下文來保存多次消息交換的狀態,這就是所謂的會話。
2) 關于 ASP.NET Core 中的會話
- 在 ASP.NET Core 中利用一個叫做 Session 的中間件來實現會話,
- 每個會話都有一個標識SessionKey,但是SessionKey不是唯一標識,是一個數據字典的形式,
- 將SessionKey保存在服務端,當會話中間件在處理會話的第一個請求的時候,會創建一個SessionKey
- 并基于它創建一個獨立的數據字典來存儲會話狀態,應用程序設置的會話狀態都是自動保存在當前會話對應的數據字典中的
- 這個SessionKey最終會以 Cookie 的形式寫入響應并返回給客戶端,
- 客戶端在每次發起請求的時候都會附加這個 Cookie,從而使我們的應用程序能夠準確定位到當前會話對應的數據字典。
一、配置會話中間件
配置基于內存的分布式緩存服務和會話服務,如需要將緩存放置于數據庫可以參考微軟官方文檔
public void ConfigureServices(IServiceCollection services) { // 添加基于內存的緩存服務,以供會話中間件來使用 collection.AddDistributedMemoryCache(); // 添加會話 collection.AddSession(); }
添加會話中間件
public void Configure(IApplicationBuilder app) { // 引入會話中間件 app.UseSession(); }
二、會話狀態的讀寫
寫入Session
ISession session = httpContext.Session; var sessionStartTime = DateTime.Now.ToString(CultureInfo.InvariantCulture); session.SetString("SessionStartTime", sessionStartTime);
讀取Session
ISession session = httpContext.Session; session.TryGetValue("SessionStartTime", out var value); var sessionStartTime = Encoding.UTF8.GetString(value);
獲取SessionId
ISession session = httpContext.Session; session.TryGetValue("SessionStartTime", out var value); var sessionStartTime = Encoding.UTF8.GetString(value);
獲取SessionKey
SessionKey 需要通過反射獲取
ISession session = httpContext.Session; var field = typeof(DistributedSession).GetTypeInfo() .GetField("_sessionKey", BindingFlags.Instance | BindingFlags.NonPublic); var sessionKey = field?.GetValue(session);
三、 示例的生命周期
這里準備了示例的代碼:
app.UseEndpoints(endpoints => { endpoints.MapGet("/get", async httpContext => { ISession session = httpContext.Session; string sessionStartTime; if (session.TryGetValue("SessionStartTime", out var value)) { sessionStartTime = Encoding.UTF8.GetString(value); } else { sessionStartTime = DateTime.Now.ToString(CultureInfo.InvariantCulture); session.SetString("SessionStartTime", sessionStartTime); } var field = typeof(DistributedSession).GetTypeInfo() .GetField("_sessionKey", BindingFlags.Instance | BindingFlags.NonPublic); var sessionKey = field?.GetValue(session); var responseText = $@" <html> <body> <h1>Get Session</h1> <ul> <li>Session ID:{session.Id}</li> <li>Session Key:{sessionKey}</li> <li>Session Start Time:{sessionStartTime}</li> <li>Current Time:{DateTime.Now:yyyy-MM-dd HH:mm:ss}</li> </ul> </body> </html>"; httpContext.Response.ContentType = "text/html"; await httpContext.Response.WriteAsync(responseText); }); });
清除瀏覽器中的 Cookie,然后刷新頁面進入/get
頁面中,可以看到在新的網絡請求中響應標頭多了一個 set-cookie,這個set-cookie是被加密的SessionKey,還具有 httponly 的標簽,以防止Cookie 的值被跨站讀取。
默認請求下 Cookie 采用的路徑是根路徑
然后我們重新刷新頁面,可以看到請求標頭中多出一個 cookie,就是之前的 set-cookie,因為之前緩存被清除以后,第一次刷新標頭多一個 set-cookie,相當于創建一個新的會話,當下一次發起請求就會帶上 cookie。
四、其他
- SessionId 可以作為會話的唯一標識,但是 SessionKey 不可以
- 也就是說兩個不同的 Session,肯定具有不同的 SessionId,但是他們有可能共享相同的SessionKey
- 當會話中間件接收到會話的第一個請求的時候,他會創建兩個不同的 guid,分別表示 SessionKey 和 SessionId
- 其中 SessionId 將被作為會話狀態的一部分被存儲起來,而 SessionKey 則會以會話的形式返回給客戶端
- 會話一般都是有有效期的,而會話的有效期基本決定了存儲的會話狀態數據的有效期
- 默認情況下 ASP.NET Core 應用的會話它所采用的默認過期時間是20分鐘, 默認情況下20分鐘內的任意請求都會將會話的壽命延長再延長
- 兩次請求的時間超過了有效期,意味著這個會話過期,存儲的會話狀態數據包括 SessionId 也都會被清除
- 但是請求攜帶的 SessionKey 可能還是原來的 SessionKey
- 在這種請求下,會話中間件會創建一個新的會話,這個新的會話具有不同的 SessionId,但是整個會話狀態仍然會沿用原來的 SessionKey
- 所以 SessionKey 不能作為會話的唯一標識,它只代表存儲數據的標識
- 會話本質上就是在應用的層面上提供了一個數據容器來保存客戶端的狀態,這個客戶端狀態就是會話狀態,會話的核心功能就是會話狀態的讀寫
原文鏈接:https://blog.csdn.net/Upgrader/article/details/114271949
相關推薦
- 2022-06-27 使用Golang搭建web服務的實現步驟_Golang
- 2022-05-05 碎片拼接技術恢復XenServer服務器SQL?Server數據庫數據_XenServer
- 2022-04-26 EF?Core通過顯式編譯提高查詢性能_實用技巧
- 2022-07-15 Android拖拽助手ViewDragHelper的創建與使用實例_Android
- 2022-05-13 error hawk@0.10.2: The engine “node“ is incompatib
- 2022-04-01 K8s產生ERROR的解決方法
- 2022-07-12 Android廣播和消息跨進程通信并返回數據
- 2022-08-11 golang時間及時間戳的獲取轉換_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支