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

ASP.NET Core 6.0 Razor Pages:如何将登录用户信息存入Session?

解决方案

针对你的需求,有几种简便且可靠的实现方式,无需强制所有页面模型继承基类:

1. 利用OpenID Connect认证成功事件钩子(推荐)

在Azure AD的OpenID Connect认证流程中,OnTokenValidated事件会在用户登录成功、令牌验证通过后触发,此时HttpContext.User已完全可用,是将用户信息存入Session的最佳时机。

实现步骤:

首先确保Session中间件已正确注册(顺序很重要),然后在OIDC配置中添加事件处理:

// Program.cs
var builder = WebApplication.CreateBuilder(args);

// 注册Session服务
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromHours(1); // 根据需求设置过期时间
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

// 添加Razor Pages和认证服务
builder.Services.AddRazorPages();
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
    builder.Configuration.Bind("AzureAd", options);
    
    // 注册令牌验证成功后的事件
    options.Events = new OpenIdConnectEvents
    {
        OnTokenValidated = async context =>
        {
            // 提取userPrincipalName声明
            var userPrincipalName = context.Principal.FindFirstValue(ClaimTypes.UserPrincipalName);
            
            if (!string.IsNullOrEmpty(userPrincipalName))
            {
                // 将信息存入Session
                await context.HttpContext.Session.SetString("UserPrincipalName", userPrincipalName);
                // 可按需存入其他声明,比如DisplayName等
                var displayName = context.Principal.FindFirstValue(ClaimTypes.DisplayName);
                if (!string.IsNullOrEmpty(displayName))
                {
                    await context.HttpContext.Session.SetString("DisplayName", displayName);
                }
            }
        }
    };
});

var app = builder.Build();

// 中间件顺序:Session必须在Authentication之前
app.UseSession();
app.UseAuthentication();
app.UseAuthorization();

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

优点:仅在用户登录成功时执行一次,性能开销小,逻辑直接对应认证成功的时机。

2. 使用全局Razor Pages页面过滤器

Razor Pages支持页面过滤器(IAsyncPageFilter/IPageFilter),可以全局注册一个过滤器,在每次页面请求时检查用户是否已认证,若Session中无用户信息则自动存入。

实现步骤:

  1. 创建全局页面过滤器类:
public class UserSessionPageFilter : IAsyncPageFilter
{
    public async Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
    {
        // 此阶段无需处理,留空即可
    }

    public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
    {
        var httpContext = context.HttpContext;
        
        // 检查用户是否已认证,且Session中未存储用户信息
        if (httpContext.User.Identity.IsAuthenticated && 
            string.IsNullOrEmpty(httpContext.Session.GetString("UserPrincipalName")))
        {
            var userPrincipalName = httpContext.User.FindFirstValue(ClaimTypes.UserPrincipalName);
            if (!string.IsNullOrEmpty(userPrincipalName))
            {
                await httpContext.Session.SetString("UserPrincipalName", userPrincipalName);
            }
        }

        // 继续执行后续处理
        await next();
    }
}
  1. 在Program.cs中注册全局过滤器:
builder.Services.AddScoped<IAsyncPageFilter, UserSessionPageFilter>();

优点:自动处理Session过期或重新登录的场景,确保每次请求时Session中都有最新的用户信息;无需修改现有页面模型。

3. 不推荐的方案:基类继承

虽然创建基类让所有PageModel继承可以实现需求,但这种方式会增加代码耦合度,后续维护和扩展成本更高,不如上述两种方案灵活简便。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:43:20