在ASP.NET Core应用采用多实例负载均衡部署的场景下,默认的进程内Session存储无法满足跨实例会话共享的需求,实现分布式会话是保障用户会话一致性的核心方案。分布式会话的核心是将Session数据从应用进程内转移到外部的共享存储中,所有应用实例都从同一个存储中读写会话数据,从而实现会话状态的共享。

分布式会话实现核心原理
ASP.NET Core的Session功能基于IDistributedCache接口实现,该接口定义了分布式缓存的通用操作规范,支持多种存储后端。当启用分布式Session后,框架会将Session数据序列化后存储到IDistributedCache对应的存储中,每次请求时从存储中加载当前用户的Session数据,请求结束后将变更同步回存储。
常用的IDistributedCache实现包括内存缓存、Redis缓存、SQL Server缓存等,生产环境推荐使用Redis作为存储后端,因为其支持持久化、高可用且读写性能优异。
基于Redis的分布式Session配置步骤
1. 安装必要的NuGet包
首先需要安装Redis缓存相关的NuGet包,在项目中执行以下命令:
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis
2. 配置分布式缓存服务
在Program.cs中注册Redis分布式缓存服务,代码如下:
var builder = WebApplication.CreateBuilder(args);
// 配置Redis分布式缓存,连接本地Redis服务,数据库编号为0
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "127.0.0.1:6379";
options.InstanceName = "DistributedSession_";
});
// 启用Session服务,设置Session过期时间为30分钟
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.Cookie.HttpOnly = true; // 防止客户端脚本读取Cookie,提升安全性
options.Cookie.IsEssential = true; // 确保GDPR合规,即使用户未同意Cookie也启用必要Session
});
var app = builder.Build();
// 启用Session中间件,必须放在路由中间件之前
app.UseSession();
app.MapGet("/", () => "Hello World!");
app.Run();
3. Session数据的读写操作
在控制器或最小API中可以通过HttpContext.Session属性操作Session数据,以下是存储和读取用户登录信息的示例:
// 最小API示例:存储用户登录信息到Session
app.MapPost("/login", (HttpContext context, string userName) =>
{
// 存储字符串类型的Session值
context.Session.SetString("UserName", userName);
// 存储整数类型的Session值,需要手动转换字节数组
context.Session.SetInt32("UserId", 1001);
return "登录信息已保存到分布式Session";
});
// 最小API示例:从Session读取用户登录信息
app.MapGet("/userinfo", (HttpContext context) =>
{
var userName = context.Session.GetString("UserName");
var userId = context.Session.GetInt32("UserId");
if (string.IsNullOrEmpty(userName))
{
return "未检测到登录信息";
}
return $"用户ID:{userId},用户名:{userName}";
});
复杂对象的Session存储
如果需要存储自定义对象到Session中,需要先将对象序列化为字符串或字节数组,以下是使用System.Text.Json序列化的示例:
using System.Text.Json;
// 定义用户实体类
public class UserDto
{
public int Id { get; set; }
public string Name { get; set; }
public string Role { get; set; }
}
// 存储复杂对象到Session的扩展方法
public static class SessionExtensions
{
public static void SetObject<T>(this ISession session, string key, T value)
{
var jsonStr = JsonSerializer.Serialize(value);
session.SetString(key, jsonStr);
}
public static T GetObject<T>(this ISession session, string key)
{
var jsonStr = session.GetString(key);
if (string.IsNullOrEmpty(jsonStr))
{
return default;
}
return JsonSerializer.Deserialize<T>(jsonStr);
}
}
// 使用扩展方法存储和读取复杂对象
app.MapPost("/saveuser", (HttpContext context) =>
{
var user = new UserDto
{
Id = 1002,
Name = "测试用户",
Role = "Admin"
};
context.Session.SetObject("CurrentUser", user);
return "用户对象已保存到Session";
});
app.MapGet("/getuser", (HttpContext context) =>
{
var user = context.Session.GetObject<UserDto>("CurrentUser");
if (user == null)
{
return "未找到用户对象";
}
return $"用户ID:{user.Id},名称:{user.Name},角色:{user.Role}";
});
注意事项与常见问题
- Redis连接字符串需要根据实际部署环境调整,如果Redis配置了密码,需要在Configuration中添加密码参数,格式为
127.0.0.1:6379,password=yourpassword。 - Session的Cookie名称默认是
.AspNetCore.Session,可以通过options.Cookie.Name自定义,避免多应用部署时的Cookie冲突。 - 分布式Session的读写性能依赖于Redis的响应速度,建议对Redis做主从复制或集群部署,提升可用性和读写性能。
- 敏感数据不建议直接存储到Session中,即使Session数据存储在Redis中,也需要做好Redis的访问权限控制,避免数据泄露。
- 如果应用部署在反向代理之后,需要正确配置转发的请求头,确保Session的Cookie路径和域名设置正确,避免Session丢失。
异常处理建议
在使用分布式Session时,可能会遇到Redis连接失败、序列化失败等异常,建议在代码中添加异常处理逻辑,例如:
app.MapGet("/safeget", (HttpContext context) =>
{
try
{
var userName = context.Session.GetString("UserName");
return string.IsNullOrEmpty(userName) ? "未登录" : $"当前用户:{userName}";
}
catch (Exception ex)
{
// 记录异常日志,返回友好提示
// 实际项目中可以注入ILogger记录日志
return "获取会话信息失败,请稍后重试";
}
});
C#ASP.NET Core分布式SessionRedisIDistributedCache修改时间:2026-07-02 16:12:26