一、简介:

1、ASP.NET Core 通过向客户端提供包含会话 ID 的 cookie 来维护会话状态。 cookie 会话 ID:

  • 会随每个请求发送到应用。
  • 由应用用于提取会话数据。

2、会话状态具有以下行为:

  • 会话 cookie 特定于浏览器。 会话不会跨浏览器进行共享。
  • 浏览器会话结束时删除会话 cookie。
  • 如果收到过期的会话 cookie,则创建使用相同会话 cookie 的新会话。
  • 不会保留空会话。 会话中必须设置了至少一个值以保存所有请求的会话。 会话未保留时,为每个新的请求生成新会话 ID。
  • 应用在上次请求后保留会话的时间有限。 应用设置会话超时,或者使用 20 分钟的默认值。 在以下情况下,会话状态适合存储用户数据:
  • 特定于某个特定会话。
  • 数据不需要跨会话永久存储。
  • 会话数据在调用  ISession.Clear 实现或会话到期时删除。
  • 没有默认机制告知客户端浏览器已关闭或者客户端上的会话 cookie 被删除或过期的应用代码。
  • 默认情况下,会话状态 cookie 不标记为“基本”。 除非站点访问者允许跟踪,否则会话状态不起作用。 有关详细信息,请参阅  ASP.NET Core 中的一般数据保护条例 (GDPR) 支持
  • 注意:ASP.NET 框架中的无 cookie 会话功能没有替代,因为它被视为不安全,可能导致会话修复攻击。

3、内存中缓存提供程序在应用驻留的服务器内存中存储会话数据。 在服务器场方案中:

二、使用

先随便贴点代码

1、WebApi_Net7使用Session
// 开启Session
using Microsoft.AspNetCore.CookiePolicy;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using System;
using System.Net.Http;

namespace fly_chat1_net7
{
    public class Program
    {
        public static void Main(string[] args)
        {
            // try前也可能报错,但是错误是可控的。实际项目中使用时可以再加个try,只记录日志到文件中。
            var configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())  // 设置“configuration”的查找目录为程序目录
                .AddJsonFile("appsettings.json")  // 设置“configuration”的读取文件
                .Build();  // 获取配置
                var builder = WebApplication.CreateBuilder(args);
                // 中间件知识https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-6.0#order
                #region 容器Services
                builder.Services.AddControllers();            // 添加Controller
                builder.Services.AddHttpContextAccessor();    // 操作Http上下文;比如:AOP里面可以获取IOC对象
                builder.Services.AddEndpointsApiExplorer();   // ASP.NET Core自身提供;Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
                #region Cookie与Session
                //builder.Services.AddCookiePolicy(options =>  // 要自定义Session使用的Cookie配置时打开这个
                //{
                //    options.MinimumSameSitePolicy = SameSiteMode.Lax;  // 限制只使用同站Cookie;Chrome 51 开始,浏览器的 Cookie 新增加了一个SameSite属性,用来防止 CSRF 攻击和用户追踪。SameSiteMode.Lax 允许 OAuth2身份验证,如Get请求;SameSiteMode.Strict 严格执行同一站点策略。
                //    options.Secure = CookieSecurePolicy.None;          // 标识Cookie是否必须是https。该属性在SameSite=None的场景下生效;CookieSecurePolicy.None为允许Https/Http,CookieSecurePolicy.Always为只允许Https;CookieSecurePolicy.SameAsRequest为登录页的URI是Https时则只允许Https,URI是Http时则允许Http/Https。
                //    options.HttpOnly = HttpOnlyPolicy.None;            // 是否只在Http请求中启用Cookie
                //    options.CheckConsentNeeded = _ => true;            // 检查用户是否位于欧盟(EU)或欧洲经济区(EEA);是则弹出一个页面让用户同意Cookie跟踪策略。默认是“false”
                //    options.ConsentCookieValue = "true";               // 是否弹出一个页面让用户同意Cookie跟踪策略;默认为“是”。与CheckConsentNeeded类似。
                //    options.ConsentCookie = new CookieBuilder()        // options.CheckConsentNeeded或options.ConsentCookieValue弹出页面的内容
                //    {
                //        Name = configuration["AppName"],     // Cookie名字
                //        Expiration = TimeSpan.FromHours(6),  // Cookie过期时间-6小时
                //        MaxAge = TimeSpan.FromHours(6),      // Cookie最大生命周期-6小时;Expiration与MaxAge如果同时使用,MaxAge会生效;推荐使用MaxAge。
                //        IsEssential = false,                 // 是否可绕过"检查同意政策",默认为false不绕过
                //    };
                //    //options.OnAppendCookie = CheckSameCookie => { };  // cookie添加事件-记录Cookie变化或者检查是否有相同的Cookie
                //    //options.OnDeleteCookie = AddCookieLog => { };     // cookie删除事件-记录Cookie变化
                //});

                builder.Services.AddDistributedMemoryCache();   // 启用MemoryCache分布式缓存(启用Session时必须启用)
                builder.Services.AddSession(options =>  // 配置Session
                {
                    options.IdleTimeout = TimeSpan.FromHours(6);   // 当Session空闲时会被框架回收,这里设置回收的时间。 此设置仅适用于会话内容,不适用于 cookie。 默认为 20 分钟。
                    options.IOTimeout = TimeSpan.FromSeconds(30);  // 允许从存储加载会话或者将其提交回存储的最大时长。 此设置可能仅适用于异步操作。默认是1分钟,我们这里使用30秒吧
                    options.Cookie.HttpOnly = true;     // 这个就是和AddCookiePolicy()是一样的效果了
                    options.Cookie.IsEssential = true;  // 这个就是和AddCookiePolicy()是一样的效果了
                });
                #endregion Cookie与Session
                #endregion 容器Services

                var app = builder.Build();

                app.UseHttpLogging();
                app.UseHttpsRedirection();
                app.UseStaticFiles();  // 在UseRouting()前
                app.UseRouting();

                app.UseAuthorization();
                app.UseSession();  // 使用Session

                app.MapControllers();
                app.Run();
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
2、Session读写值使用示例
HttpContext对象.Session.Get("KeyName");
  HttpContext对象.Session.GetInt32("KeyName");
  HttpContext对象.Session.GetString("KeyName");
  HttpContext对象.Session.SetInt32("KeyName", 73);
  HttpContext对象.Session.SetString("KeyName", "内容");
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
3、SessionExtensions扩展类
/*
SessionExtensions方法
使用示例:
  if (HttpContext.Session.Get<DateTime>(SessionKeyTime) == default)
  {
     HttpContext.Session.Set<DateTime>(SessionKeyTime, currentTime);
  }
   HttpContext.Session.Get<DateTime>(SessionKeyTime));
*/
public static class SessionExtensions
{
    public static void Set<T>(this ISession session, string key, T value)
    {
        session.SetString(key, JsonSerializer.Serialize(value));
    }

    public static T? Get<T>(this ISession session, string key)
    {
        var value = session.GetString(key);
        return value == null ? default : JsonSerializer.Deserialize<T>(value);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.

作者:꧁执笔小白꧂