You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

ASP.NET Core Razor应用:闲置10分钟及关闭浏览器时清除ISession

实现ASP.NET Core Razor应用中两种场景的会话清除

一、会话闲置10分钟自动清除

ASP.NET Core的ISession原生支持配置闲置超时,结合Cookie配置即可实现基础的超时清除逻辑,还可扩展主动清理关联业务资源的逻辑。

1. 配置Session与Cookie

Program.cs中设置Session的闲置超时时间,并配置安全的Cookie属性:

builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(10); // 闲置10分钟后会话过期
    options.Cookie.HttpOnly = true; // 禁止前端脚本访问Cookie,提升安全性
    options.Cookie.IsEssential = true; // 标记为必要Cookie,适配隐私合规要求
    // 不设置Cookie.Expires,保持默认会话Cookie特性(浏览器关闭即失效)
});

// 注册Session中间件(需放在UseRouting之后、UseEndpoints之前)
app.UseSession();

2. 主动清理关联资源(可选)

服务器会自动标记超时会话为过期,但如果需要同步清理用户关联的缓存或业务数据,可在请求流程中检查会话的最后活动时间:

先实现Session扩展方法,用于存储和读取最后活动时间:

public static class SessionExtensions
{
    public static void SetLastActivity(this ISession session, DateTime timestamp)
    {
        session.SetString("LastActivity", timestamp.ToString("o"));
    }

    public static DateTime? GetLastActivity(this ISession session)
    {
        var value = session.GetString("LastActivity");
        return value == null ? null : DateTime.Parse(value);
    }
}

然后在Razor页面的请求处理方法中检查并清理:

public class IndexModel : PageModel
{
    public void OnGet()
    {
        var lastActivity = HttpContext.Session.GetLastActivity();
        if (lastActivity.HasValue && lastActivity.Value.AddMinutes(10) < DateTime.UtcNow)
        {
            // 清除当前会话数据
            HttpContext.Session.Clear();
            // 清理用户关联的其他资源(如分布式缓存中的用户业务数据)
            var cache = HttpContext.RequestServices.GetRequiredService<IDistributedCache>();
            cache.Remove($"UserBusinessData:{HttpContext.Session.Id}");
        }

        // 更新最后活动时间为当前UTC时间
        HttpContext.Session.SetLastActivity(DateTime.UtcNow);
    }
}

二、用户未登出关闭所有浏览器标签页时清除会话

默认情况下,Session Cookie是会话级别的,关闭浏览器后Cookie会被删除,但服务器端的会话数据仍会保留到闲置超时。要实现即时清除,需结合前端卸载事件与后端清理接口。

1. 前端监听页面卸载事件

在Razor页面中添加脚本,使用navigator.sendBeacon发送异步清理请求(该方法不会阻塞页面卸载,兼容性更优):

<script>
window.addEventListener('beforeunload', (event) => {
    // 判断是否为关闭浏览器/标签页操作(排除刷新、跳转等场景)
    const isClosing = event.clientY < 0 || event.clientX < 0 || event.altKey || event.ctrlKey || event.metaKey;
    if (isClosing) {
        // 发送会话清理请求
        navigator.sendBeacon('/ClearSession', JSON.stringify({ sessionId: '@Context.Session.Id' }));
    }
});
</script>

2. 后端实现会话清理端点

创建ClearSession.cshtml.cs页面模型,处理前端发送的清理请求:

public class ClearSessionModel : PageModel
{
    private readonly IDistributedCache _cache;

    public ClearSessionModel(IDistributedCache cache)
    {
        _cache = cache;
    }

    public async Task<IActionResult> OnPostAsync()
    {
        using var reader = new StreamReader(Request.Body);
        var body = await reader.ReadToEndAsync();
        var requestData = System.Text.Json.JsonSerializer.Deserialize<SessionClearRequest>(body);

        if (!string.IsNullOrEmpty(requestData?.SessionId) && HttpContext.Session.Id == requestData.SessionId)
        {
            // 清除当前会话数据
            HttpContext.Session.Clear();
            // 移除分布式缓存中的会话项(若使用Redis等分布式缓存)
            await _cache.RemoveAsync($"Session:{requestData.SessionId}");
        }

        return new OkResult();
    }

    private class SessionClearRequest
    {
        public string SessionId { get; set; }
    }
}

注意:该方法无法保证100%可靠(如浏览器崩溃、网络中断时请求可能无法送达),因此服务器端的闲置超时配置仍需作为兜底方案。

内容的提问来源于stack exchange,提问作者Chhotelal Gupta

火山引擎 最新活动