Сторона сервера Blazor - как использовать RevalidatingServerAuthenticationStateProvider для проверки истечения срока действия токена?

Я пытаюсь создать 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();            
    }

Внедренный объект:

Внедренный объект

ОБНОВЛЕНИЕ: должен был упомянуть об этом раньше ... В настоящее время я работаю над серверным проектом, но макеты находятся в общей библиотеке пользовательского интерфейса. Поэтому предложение, сделанное @enet, не подходит, поскольку RevalidatingServerAuthenticationStateProvider не будет доступен в общем проекте, и поэтому TokenExpiryAuthStateProvider находится только в серверном проекте.

Тем не менее, следуя предложению enet, я объявил интерфейс и обновил ConfigureServices, чтобы я мог вставить его в свой общий макет, чтобы опробовать его:

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

Затем я ввел ITokenExpiryProvider в MainLayout и подписался на событие AuthenticationStateChanged (единственное событие, которое я мог видеть). После интервала обновления состояние не было изменено, и ValidateAuthenticationStateAsync не был вызван. Как начать процесс повторной проверки и почему AddScoped ‹AuthenticationStateProvider, TokenExpiryAuthStateProvider› не работает?

Я думаю, что для моего простого варианта использования будет проще создать класс таймера, который вводится с помощью AuthenticationStateProvider; затем этот класс инкапсулирует периодическую проверку состояния аутентификации и, в свою очередь, вызывает событие, когда сеанс истекает. (Вот как я ожидал, что RevalidatingServerAuthenticationStateProvider будет работать, проверяя ValidateAuthenticationStateAsync по истечении RefreshInterval)

Я все еще хотел бы знать, почему моя реализация не работает и почему ValidateAuthenticationStateAsync никогда не вызывается; Должно быть, я как-то неправильно регистрирую сервис.


person Matt Conway    schedule 25.09.2020    source источник


Ответы (1)


У меня была такая же проблема в приложении Blazor Server при реализации моего собственного RevalidatingServerAuthenticationStateProvider. Я обнаружил, что эта проблема связана с тем, как все настроено в Startup.cs.

Вызывая services.AddRazorPages() и services.AddServerSideBlazor() перед настройкой поставщиков аутентификации, я исправил проблему, и теперь мой метод ValidationAuthenticationStateAsync() вызывается в указанном RevalidationInterval.

Вот сокращенная версия метода ConfigureServices(...) в моем Startup.cs в качестве примера:

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>();
}
person mkchandler    schedule 08.12.2020