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

Blazor自定义认证系统刷新页面后自动登出问题求助

刷新页面自动登出的问题修复方案

问题原因拆解

  1. 登录异步操作无效:你在MarkUserAsAuthenticated里用Task.Run包裹SignInAsync,还没等它执行完成就通知了认证状态变更。Blazor Server环境下HttpContext仅在当前请求的上下文内有效,新开线程后HttpContext会变为null,等于SignInAsync根本没执行成功,浏览器没拿到认证Cookie,刷新后自然就登出了。
  2. 认证状态读取逻辑有漏洞:GetAuthenticationStateAsync里仅当HttpContext.User已认证时才更新_currentUser,但没考虑HttpContext为空的情况(Blazor用SignalR交互时HttpContext会为空);而且每次刷新页面,CustomAuthenticationStateProvider会重新实例化,_currentUser会被重置为未认证状态。

具体修复步骤

1. 修改登录方法,移除多余线程

删掉Task.Run,直接等待SignInAsync完成,确保认证Cookie能正确写入浏览器:

public async Task MarkUserAsAuthenticated(string username, string role)
{
    var identity = new ClaimsIdentity(new[]
    {
        new Claim(ClaimTypes.Name, username),
        new Claim(ClaimTypes.Role, role)
    }, CookieAuthenticationDefaults.AuthenticationScheme);

    _currentUser = new ClaimsPrincipal(identity);
    
    var authProperties = new AuthenticationProperties
    {
        IsPersistent = true,
        ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(60)
    };

    // 直接等待SignInAsync执行完成,不要开启新线程
    await _httpContextAccessor.HttpContext.SignInAsync(
        CookieAuthenticationDefaults.AuthenticationScheme,
        _currentUser,
        authProperties);

    NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_currentUser)));
}

2. 完善认证状态读取逻辑

确保无论HttpContext是否存在,都能正确返回用户状态:

public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
    ClaimsPrincipal user;

    // 仅当HttpContext存在且用户已认证时,使用HttpContext中的用户信息
    if (_httpContextAccessor.HttpContext != null && _httpContextAccessor.HttpContext.User.Identity.IsAuthenticated)
    {
        user = _httpContextAccessor.HttpContext.User;
        _currentUser = user;
    }
    else
    {
        // 否则使用缓存的用户状态
        user = _currentUser;
    }

    return Task.FromResult(new AuthenticationState(user));
}

3. 检查Program.cs的配置

确认已正确添加Cookie认证及相关服务:

// 添加Cookie认证配置
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.LoginPath = "/Login"; // 替换为你的登录页面路径
        options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
        options.SlidingExpiration = true;
    });

// 注册必要服务
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
builder.Services.AddAuthorization();

4. 确认App.razor的授权组件包裹

确保路由被CascadingAuthenticationState包裹,让所有子组件能获取到认证状态:

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <p role="alert">抱歉,这个地址不存在。</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

验证修复效果

登录后按F12打开开发者工具,切换到Application标签查看Cookie,确认存在.AspNetCore.Cookies的Cookie;刷新页面后再次检查该Cookie是否存在,同时验证页面是否保持登录状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 12:57:33