You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core自动登录(Remember Me)时如何捕获用户访问并记录ID?

解决方案:Razor Web应用中捕获自动登录用户的访问行为

在ASP.NET Core Razor应用中,没有直接对应经典ASP Session_OnStart的事件,但可以通过以下两种方案实现自动登录用户的访问记录:

方案一:全局请求拦截中间件

通过自定义中间件拦截所有请求,判断用户是否已认证(包括自动登录的持久Cookie用户),并执行访问记录操作。

步骤1:创建访问日志中间件

public class VisitLoggingMiddleware
{
    private readonly RequestDelegate _next;

    public VisitLoggingMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context, ApplicationDbContext dbContext)
    {
        // 仅处理已认证用户
        if (context.User.Identity.IsAuthenticated)
        {
            // 用HttpContext.Items标记,避免同一次请求重复记录
            if (!context.Items.ContainsKey("HasLoggedVisit"))
            {
                var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
                if (!string.IsNullOrEmpty(userId))
                {
                    // 写入数据库操作
                    var visitLog = new VisitLog
                    {
                        UserId = userId,
                        VisitTime = DateTime.UtcNow,
                        IpAddress = context.Connection.RemoteIpAddress?.ToString(),
                        RequestPath = context.Request.Path.ToString()
                    };
                    dbContext.VisitLogs.Add(visitLog);
                    await dbContext.SaveChangesAsync();

                    context.Items["HasLoggedVisit"] = true;
                }
            }
        }

        // 传递请求到下一个中间件
        await _next(context);
    }
}

// 扩展方法:注册中间件
public static class VisitLoggingMiddlewareExtensions
{
    public static IApplicationBuilder UseVisitLogging(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<VisitLoggingMiddleware>();
    }
}

步骤2:注册中间件

在Program.cs中,将中间件放在认证中间件之后,确保能获取到已认证用户信息:

var app = builder.Build();

// ...其他中间件配置(如静态文件、路由等)

app.UseAuthentication();
app.UseAuthorization();

// 注册访问日志中间件
app.UseVisitLogging();

app.MapRazorPages();
app.Run();

方案二:Razor Pages基类统一处理

如果是Razor Pages应用,可以创建一个基类PageModel,让所有页面继承该类,在页面处理逻辑执行前完成访问记录。

步骤1:创建基类PageModel

public class BaseVisitLoggedPageModel : PageModel
{
    private readonly ApplicationDbContext _dbContext;
    private bool _visitLogged;

    public BaseVisitLoggedPageModel(ApplicationDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public override async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
    {
        if (User.Identity.IsAuthenticated && !_visitLogged)
        {
            var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
            if (!string.IsNullOrEmpty(userId))
            {
                var visitLog = new VisitLog
                {
                    UserId = userId,
                    VisitTime = DateTime.UtcNow,
                    PagePath = context.HttpContext.Request.Path.ToString()
                };
                _dbContext.VisitLogs.Add(visitLog);
                await _dbContext.SaveChangesAsync();
                _visitLogged = true;
            }
        }

        await base.OnPageHandlerExecutionAsync(context, next);
    }
}

步骤2:页面继承基类

所有需要记录访问的页面,让其PageModel继承BaseVisitLoggedPageModel:

public class IndexModel : BaseVisitLoggedPageModel
{
    public IndexModel(ApplicationDbContext dbContext) : base(dbContext)
    {
    }

    public void OnGet()
    {
        // 页面业务逻辑
    }
}

关键注意事项

  • 避免重复记录:使用HttpContext.Items或类内标记,防止同一次请求触发多次数据库写入。
  • 性能优化:如果需要记录大量请求,可将数据库写入操作放入后台任务(如IHostedService)批量处理,避免阻塞请求响应。
  • 用户ID获取:确保ClaimTypes.NameIdentifier对应你系统中用户ID的Claim类型,若为自定义认证体系,需调整为对应的Claim键名。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 21:52:53