【问题标题】:Blazor Server Side - How to use RevalidatingServerAuthenticationStateProvider to keep checking token expiry?Blazor 服务器端 - 如何使用 RevalidatingServerAuthenticationStateProvider 继续检查令牌到期?
【发布时间】:2021-01-11 22:00:15
【问题描述】:

我正在尝试创建 RevalidatingServerAuthenticationStateProvider 来检查 ClaimsPrincipal 是否已过期。

我已经创建了它的实现 (TokenExpiryAuthStateProvider) 并在 ConfigureServices 中注册了它,但是构造函数从未被调用过,ValidateAuthenticationStateAsync 也不会被调用。 (我也试过实现工厂注册,结果一样)

我将 AuthStateProvider 注入 MainLayout 以查看注入的内容,它仍在注入 ServerAuthenticationStateProvider。 我做错了什么?

我从未调用过的实现:

public class TokenExpiryAuthStateProvider : RevalidatingServerAuthenticationStateProvider
{
    protected override TimeSpan RevalidationInterval => TimeSpan.FromSeconds(10);

    public TokenExpiryAuthStateProvider(ILoggerFactory logger) : base(logger)
    {

    }

    protected override Task<bool> ValidateAuthenticationStateAsync(AuthenticationState authenticationState, CancellationToken cancellationToken)
    {
        DateTime expiry = authenticationState.User.GetExpiryDate();

        if (expiry < DateTime.UtcNow)
            return Task.FromResult(false);
        else
            return Task.FromResult(true);
    }
}

配置服务

public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<HttpClientFactory>();

        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
        services.ConfigureApplicationCookie(options =>
        {
            options.Cookie.HttpOnly = true;
            options.SlidingExpiration = true;
            options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
        });

        services.AddScoped<AuthenticationStateProvider, TokenExpiryAuthStateProvider>();

        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddHttpContextAccessor();

        services.AddCsla().WithBlazorServerSupport();            
    }

注入的对象:

更新: 之前应该提到过这个......我目前正在开发一个服务器端项目,但布局在一个共享的 ui 库中。因此,@enet 提出的建议不适合,因为 RevalidatingServerAuthenticationStateProvider 在共享项目中不可用,因此 TokenExpiryAuthStateProvider 仅在服务器项目中。

不过,根据 enet 的建议,我声明了一个接口并更新了 ConfigureServices,以便我可以将它注入我的共享布局中进行尝试:

services.AddScoped<TokenExpiryAuthStateProvider>();
services.AddScoped<ITokenExpiryProvider>(provider => 
        provider.GetRequiredService<TokenExpiryAuthStateProvider>());

然后我向 MainLayout 注入了一个 ITokenExpiryProvider,并订阅了 AuthenticationStateChanged 事件(我能看到的唯一事件)。在刷新间隔之后,没有触发任何状态更改,也没有调用 ValidateAuthenticationStateAsync。 如何启动重新验证过程以及为什么 AddScoped 不起作用?

我认为对于我的简单用例,创建一个注入 AuthenticationStateProvider 的计时器类会更容易;然后,此类封装对身份验证状态的定期检查,并在会话到期时反过来引发事件。 (这就是我期望 RevalidatingServerAuthenticationStateProvider 工作的方式,只要 RefreshInterval 过去就检查 ValidateAuthenticationStateAsync

我仍然想知道为什么我的实现不起作用以及为什么 ValidateAuthenticationStateAsync 从未被调用;我一定是以某种方式错误地注册了服务。

【问题讨论】:

    标签: blazor blazor-server-side asp.net-blazor


    【解决方案1】:

    在实现我自己的 RevalidatingServerAuthenticationStateProvider 时,我在 Blazor Server 应用程序中遇到了同样的问题。我发现这个问题是Startup.cs中所有设置的顺序。

    通过在设置身份验证提供程序之前调用services.AddRazorPages()services.AddServerSideBlazor(),我纠正了问题,现在我的ValidationAuthenticationStateAsync() 方法在指定的RevalidationInterval 处被调用。

    这里以我的Startup.cs中的ConfigureServices(...)方法为例:

    public void ConfigureServices(IServiceCollection services)
    {
        // These two need to be called before adding authentication
        services.AddRazorPages();
        services.AddServerSideBlazor();
    
        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        })
        .AddCookie()
        .AddOpenIdConnect();
    
        // This needs to be setup after setting up Blazor
        services.AddScoped<AuthenticationStateProvider, CustomRevalidatingAuthenticationStateProvider>();
    }
    

    【讨论】:

      【解决方案2】:

      正如 MkChandler 所说,我正在调查为什么在服务器端将 AuthenticationStateProvider 转换为导致错误的 ServerAuthenticationStateProvider

      找到这篇文章后,我将services.AddServerSideBlazor(); 移到了services.AddScoped&lt;AuthenticationStateProvider, ApiAuthenticationStateProvider&gt;(); 之前,并且成功了。

      注意:发生此问题时,我正在尝试将整个 blazor wasm 项目转换为 blazor 服务器端。

      【讨论】:

        猜你喜欢
        • 2013-11-22
        • 2020-06-09
        • 1970-01-01
        • 2020-08-20
        • 2022-11-09
        • 1970-01-01
        • 2020-10-14
        • 2020-05-10
        • 2020-09-19
        相关资源
        最近更新 更多