欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

ASP.NET Core中間件會(huì)話狀態(tài)讀寫(xiě)及生命周期示例

 更新時(shí)間:2022年04月28日 15:04:27   作者:Upgrader  
這篇文章主要為大家介紹了ASP.NET Core中間件會(huì)話狀態(tài)讀寫(xiě)及生命周期示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言:

本文使用 .NET Core SDK 3.1 的版本。

1) 關(guān)于Http中的會(huì)話

  • Http是一種采用請(qǐng)求響應(yīng)消息交換模式,且無(wú)狀態(tài)的傳輸協(xié)議。
  • 該協(xié)議確??蛻舳藢⒄?qǐng)求報(bào)文發(fā)送給目標(biāo)服務(wù)器并接收來(lái)自服務(wù)端的響應(yīng)報(bào)文,這個(gè)報(bào)文交換是一個(gè)Http事務(wù)。
  • 從協(xié)議的角度講,即使在使用長(zhǎng)連接的情況下,同一個(gè)客戶端和服務(wù)器之間進(jìn)行多個(gè)Http事務(wù)也是完全獨(dú)立的
  • 所以需要在應(yīng)用層為兩者去建立一個(gè)上下文來(lái)保存多次消息交換的狀態(tài),這就是所謂的會(huì)話。

2) 關(guān)于 ASP.NET Core 中的會(huì)話

  • 在 ASP.NET Core 中利用一個(gè)叫做 Session 的中間件來(lái)實(shí)現(xiàn)會(huì)話,
  • 每個(gè)會(huì)話都有一個(gè)標(biāo)識(shí)SessionKey,但是SessionKey不是唯一標(biāo)識(shí),是一個(gè)數(shù)據(jù)字典的形式,
  • 將SessionKey保存在服務(wù)端,當(dāng)會(huì)話中間件在處理會(huì)話的第一個(gè)請(qǐng)求的時(shí)候,會(huì)創(chuàng)建一個(gè)SessionKey
  • 并基于它創(chuàng)建一個(gè)獨(dú)立的數(shù)據(jù)字典來(lái)存儲(chǔ)會(huì)話狀態(tài),應(yīng)用程序設(shè)置的會(huì)話狀態(tài)都是自動(dòng)保存在當(dāng)前會(huì)話對(duì)應(yīng)的數(shù)據(jù)字典中的
  • 這個(gè)SessionKey最終會(huì)以 Cookie 的形式寫(xiě)入響應(yīng)并返回給客戶端,
  • 客戶端在每次發(fā)起請(qǐng)求的時(shí)候都會(huì)附加這個(gè) Cookie,從而使我們的應(yīng)用程序能夠準(zhǔn)確定位到當(dāng)前會(huì)話對(duì)應(yīng)的數(shù)據(jù)字典。

一、配置會(huì)話中間件

配置基于內(nèi)存的分布式緩存服務(wù)和會(huì)話服務(wù),如需要將緩存放置于數(shù)據(jù)庫(kù)可以參考微軟官方文檔

	public void ConfigureServices(IServiceCollection services)
	{
		// 添加基于內(nèi)存的緩存服務(wù),以供會(huì)話中間件來(lái)使用
        collection.AddDistributedMemoryCache();
        // 添加會(huì)話
        collection.AddSession();
	}

添加會(huì)話中間件

	public void Configure(IApplicationBuilder app)
	{
		// 引入會(huì)話中間件
		app.UseSession();
	}

二、會(huì)話狀態(tài)的讀寫(xiě)

寫(xiě)入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 需要通過(guò)反射獲取

    ISession session = httpContext.Session;
    var field = typeof(DistributedSession).GetTypeInfo()
        .GetField("_sessionKey", BindingFlags.Instance | BindingFlags.NonPublic);
    var sessionKey = field?.GetValue(session);

三、 示例的生命周期

這里準(zhǔn)備了示例的代碼:

    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,然后刷新頁(yè)面進(jìn)入/get頁(yè)面中,可以看到在新的網(wǎng)絡(luò)請(qǐng)求中響應(yīng)標(biāo)頭多了一個(gè) set-cookie,這個(gè)set-cookie是被加密的SessionKey,還具有 httponly 的標(biāo)簽,以防止Cookie 的值被跨站讀取。

默認(rèn)請(qǐng)求下 Cookie 采用的路徑是根路徑

然后我們重新刷新頁(yè)面,可以看到請(qǐng)求標(biāo)頭中多出一個(gè) cookie,就是之前的 set-cookie,因?yàn)橹熬彺姹磺宄院?,第一次刷新?biāo)頭多一個(gè) set-cookie,相當(dāng)于創(chuàng)建一個(gè)新的會(huì)話,當(dāng)下一次發(fā)起請(qǐng)求就會(huì)帶上 cookie。

四、其他

  • SessionId 可以作為會(huì)話的唯一標(biāo)識(shí),但是 SessionKey 不可以
  • 也就是說(shuō)兩個(gè)不同的 Session,肯定具有不同的 SessionId,但是他們有可能共享相同的SessionKey
  • 當(dāng)會(huì)話中間件接收到會(huì)話的第一個(gè)請(qǐng)求的時(shí)候,他會(huì)創(chuàng)建兩個(gè)不同的 guid,分別表示 SessionKey 和 SessionId
  • 其中 SessionId 將被作為會(huì)話狀態(tài)的一部分被存儲(chǔ)起來(lái),而 SessionKey 則會(huì)以會(huì)話的形式返回給客戶端
  • 會(huì)話一般都是有有效期的,而會(huì)話的有效期基本決定了存儲(chǔ)的會(huì)話狀態(tài)數(shù)據(jù)的有效期
  • 默認(rèn)情況下 ASP.NET Core 應(yīng)用的會(huì)話它所采用的默認(rèn)過(guò)期時(shí)間是20分鐘, 默認(rèn)情況下20分鐘內(nèi)的任意請(qǐng)求都會(huì)將會(huì)話的壽命延長(zhǎng)再延長(zhǎng)
  • 兩次請(qǐng)求的時(shí)間超過(guò)了有效期,意味著這個(gè)會(huì)話過(guò)期,存儲(chǔ)的會(huì)話狀態(tài)數(shù)據(jù)包括 SessionId 也都會(huì)被清除
  • 但是請(qǐng)求攜帶的 SessionKey 可能還是原來(lái)的 SessionKey
  • 在這種請(qǐng)求下,會(huì)話中間件會(huì)創(chuàng)建一個(gè)新的會(huì)話,這個(gè)新的會(huì)話具有不同的 SessionId,但是整個(gè)會(huì)話狀態(tài)仍然會(huì)沿用原來(lái)的 SessionKey
  • 所以 SessionKey 不能作為會(huì)話的唯一標(biāo)識(shí),它只代表存儲(chǔ)數(shù)據(jù)的標(biāo)識(shí)
  • 會(huì)話本質(zhì)上就是在應(yīng)用的層面上提供了一個(gè)數(shù)據(jù)容器來(lái)保存客戶端的狀態(tài),這個(gè)客戶端狀態(tài)就是會(huì)話狀態(tài),會(huì)話的核心功能就是會(huì)話狀態(tài)的讀寫(xiě)

以上就是ASP.NET Core中間件會(huì)話狀態(tài)讀寫(xiě)及生命周期示例的詳細(xì)內(nèi)容,更多關(guān)于ASP.NET Core會(huì)話中間件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論