ASP.NET Core中間件會話狀態(tài)讀寫及生命周期示例
前言:
本文使用 .NET Core SDK 3.1 的版本。
1) 關于Http中的會話
- Http是一種采用請求響應消息交換模式,且無狀態(tài)的傳輸協(xié)議。
- 該協(xié)議確??蛻舳藢⒄埱髨笪陌l(fā)送給目標服務器并接收來自服務端的響應報文,這個報文交換是一個Http事務。
- 從協(xié)議的角度講,即使在使用長連接的情況下,同一個客戶端和服務器之間進行多個Http事務也是完全獨立的
- 所以需要在應用層為兩者去建立一個上下文來保存多次消息交換的狀態(tài),這就是所謂的會話。
2) 關于 ASP.NET Core 中的會話
- 在 ASP.NET Core 中利用一個叫做 Session 的中間件來實現(xiàn)會話,
- 每個會話都有一個標識SessionKey,但是SessionKey不是唯一標識,是一個數(shù)據(jù)字典的形式,
- 將SessionKey保存在服務端,當會話中間件在處理會話的第一個請求的時候,會創(chuàng)建一個SessionKey
- 并基于它創(chuàng)建一個獨立的數(shù)據(jù)字典來存儲會話狀態(tài),應用程序設置的會話狀態(tài)都是自動保存在當前會話對應的數(shù)據(jù)字典中的
- 這個SessionKey最終會以 Cookie 的形式寫入響應并返回給客戶端,
- 客戶端在每次發(fā)起請求的時候都會附加這個 Cookie,從而使我們的應用程序能夠準確定位到當前會話對應的數(shù)據(jù)字典。
一、配置會話中間件
配置基于內(nèi)存的分布式緩存服務和會話服務,如需要將緩存放置于數(shù)據(jù)庫可以參考微軟官方文檔
public void ConfigureServices(IServiceCollection services) { // 添加基于內(nèi)存的緩存服務,以供會話中間件來使用 collection.AddDistributedMemoryCache(); // 添加會話 collection.AddSession(); }
添加會話中間件
public void Configure(IApplicationBuilder app) { // 引入會話中間件 app.UseSession(); }
二、會話狀態(tài)的讀寫
寫入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
頁面中,可以看到在新的網(wǎng)絡請求中響應標頭多了一個 set-cookie,這個set-cookie是被加密的SessionKey,還具有 httponly 的標簽,以防止Cookie 的值被跨站讀取。
默認請求下 Cookie 采用的路徑是根路徑
然后我們重新刷新頁面,可以看到請求標頭中多出一個 cookie,就是之前的 set-cookie,因為之前緩存被清除以后,第一次刷新標頭多一個 set-cookie,相當于創(chuàng)建一個新的會話,當下一次發(fā)起請求就會帶上 cookie。
四、其他
- SessionId 可以作為會話的唯一標識,但是 SessionKey 不可以
- 也就是說兩個不同的 Session,肯定具有不同的 SessionId,但是他們有可能共享相同的SessionKey
- 當會話中間件接收到會話的第一個請求的時候,他會創(chuàng)建兩個不同的 guid,分別表示 SessionKey 和 SessionId
- 其中 SessionId 將被作為會話狀態(tài)的一部分被存儲起來,而 SessionKey 則會以會話的形式返回給客戶端
- 會話一般都是有有效期的,而會話的有效期基本決定了存儲的會話狀態(tài)數(shù)據(jù)的有效期
- 默認情況下 ASP.NET Core 應用的會話它所采用的默認過期時間是20分鐘, 默認情況下20分鐘內(nèi)的任意請求都會將會話的壽命延長再延長
- 兩次請求的時間超過了有效期,意味著這個會話過期,存儲的會話狀態(tài)數(shù)據(jù)包括 SessionId 也都會被清除
- 但是請求攜帶的 SessionKey 可能還是原來的 SessionKey
- 在這種請求下,會話中間件會創(chuàng)建一個新的會話,這個新的會話具有不同的 SessionId,但是整個會話狀態(tài)仍然會沿用原來的 SessionKey
- 所以 SessionKey 不能作為會話的唯一標識,它只代表存儲數(shù)據(jù)的標識
- 會話本質上就是在應用的層面上提供了一個數(shù)據(jù)容器來保存客戶端的狀態(tài),這個客戶端狀態(tài)就是會話狀態(tài),會話的核心功能就是會話狀態(tài)的讀寫
以上就是ASP.NET Core中間件會話狀態(tài)讀寫及生命周期示例的詳細內(nèi)容,更多關于ASP.NET Core會話中間件的資料請關注腳本之家其它相關文章!
相關文章
asp.net實現(xiàn)非常實用的自定義頁面基類(附源碼)
這篇文章主要介紹了asp.net實現(xiàn)非常實用的自定義頁面基類,包含日志處理、控件賦值、異常處理等功能,非常具有實用價值,需要的朋友可以參考下2015-11-11Visual Studio 2019 使用 Live Share的教程圖解
Visual Studio 2019 在今天發(fā)布(北京時間)了,這次帶來了一個比較有趣的 Live Share 功能,使用它可以進行更好的協(xié)作開發(fā)。這篇文章主要介紹了Visual Studio 2019 使用 Live Share的教程,需要的朋友可以參考下2019-04-04動態(tài)加載用戶控件至DataList并為用戶控件賦值實例演示
本文借用使用通用的新聞例子演示動態(tài)加載用戶控件至DataList并為用戶控件賦值,感興趣的朋友可以了解下2013-01-01