Как аутентифицировать пользователя с Blazor Server - PullRequest
2 голосов
/ 24 февраля 2020

У меня есть приложение Blazor Server, которое использует MongoDB в качестве базы данных, поэтому я пытаюсь реализовать аутентификацию с этим. Так что я могу использовать <Authenticted>, <AuthorizeView Roles="admin"> и другие подобные теги на страницах бритвы.

Встроенный шаблон аутентификации использует SQL Сервер, который в этом случае мне не нужен, и его нет Наглядный пример того, как сделать это самостоятельно с другой базой данных. Учитывая пример, Microsoft предоставляет здесь

using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Authorization;

namespace BlazorSample.Services
{
    public class CustomAuthStateProvider : AuthenticationStateProvider
    {
        public override Task<AuthenticationState> GetAuthenticationStateAsync()
        {
            var identity = new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.Name, "mrfibuli"),
            }, "Fake authentication type");

            var user = new ClaimsPrincipal(identity);

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

Как использовать это в приложении? Очевидно, вы не станете жестко кодировать одно значение и тип-значение как единственный источник аутентификации. Так как это должно быть параметризовано? С локальными атрибутами, такими как:

Username { get; set; }
UserType { get; set; }

В каком случае вы бы это установили?

Кроме того, как бы вы использовали это для аутентификации пользователя? У меня есть класс, добавленный в файл запуска по методу ConfigurationServices(...):

...
services.AddScoped<AuthenticationStateProvider, MongoAuthenticationStateProvider>();
...

Я не могу понять, как аутентифицировать кого-либо. Я хотел бы представить, что вы проверяете имя пользователя и пароль любым количеством способов, а затем, когда вы знаете, что это хорошо, вы go впереди и обновляете аутентификацию в. NET. Я следовал учебному пособию, в котором они предложили что-то подобное в коде:

using System;
using System.Linq;
using DocsPlatform.Services;
using System.Threading.Tasks;
using System.Security.Claims;
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Components.Authorization;

namespace DocsPlatform.Pages
{
    public class LoginBase : ComponentBase
    {
        [CascadingParameter]
        private Task<AuthenticationState> authStateTask { get; set; }
        protected string username { get; set; }
        protected string password { get; set; }

        protected async Task LoginUser()
        {
            bool isValid = true;

            isValid = dbService.ValidateUser(username, password);

            string email = dbService.GetEmail(username);

            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, username),
                new Claim(ClaimTypes.Email, email),
            };

            var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
            await HttpContext.SignInAsync(
                CookieAuthenticationDefaults.AuthenticationScheme,
                new ClaimsPrincipal(claimsIdentity));

            return NavigationManager.NavigateTo("/");
        }
    }
}

Однако навигация в возврате не работает (они не объяснили, как их код даже скомпилирован), и Метод SignInAsyn c () недоступен, как они показали. Опять же, я понятия не имею, как их код скомпилирован. Так как обычно это сделать?

Я не могу найти никаких учебных пособий, примеров и т. Д. c, кроме сотен примеров , в которых используется только встроенный SQL шаблон сервера. Где можно найти подробности о том, как это используется? Все что угодно, кроме «использовать встроенный шаблон» или ссылку на документацию здесь , будет приветствоваться, поскольку ни один из них не объяснит, как это сделать.

1 Ответ

3 голосов
/ 25 февраля 2020

Встроенный шаблон аутентификации использует SQL Сервер, который мне не нужен в данном случае, и нет четкого примера того, как сделать это самостоятельно с другой базой данных

Полагаю, вы используете ASP. NET Core Identity , верно? Если вы ищете способ использования других провайдеров, см. официальные документы

Как использовать это в приложении? Очевидно, вы не станете жестко кодировать одно значение и тип-значение как единственный источник аутентификации. Так как это должно быть параметризовано?

Поскольку вы используете Blazor Server (вместо Blazor Wasm), вам не нужно настраивать метод GetAuthenticationStateAsync(), а затем создавать принципала вручную. Уже есть встроенный ServerAuthenticationStateProvider, который наследуется от AuthenticationStateProvider и реализует интерфейс IHostEnvironmentAuthenticationStateProvider:

// source code of the built-in ServerAuthenticationStateProvider 
public class ServerAuthenticationStateProvider : AuthenticationStateProvider, IHostEnvironmentAuthenticationStateProvider
{
    private Task<AuthenticationState> _authenticationStateTask;

    /// <inheritdoc />
    public override Task<AuthenticationState> GetAuthenticationStateAsync()
        => _authenticationStateTask
        ?? throw new InvalidOperationException($"{nameof(GetAuthenticationStateAsync)} was called before {nameof(SetAuthenticationState)}.");

    /// <inheritdoc />
    public void SetAuthenticationState(Task<AuthenticationState> authenticationStateTask)
    {
        _authenticationStateTask = authenticationStateTask ?? throw new ArgumentNullException(nameof(authenticationStateTask));
        NotifyAuthenticationStateChanged(_authenticationStateTask);
    }
}

Как вы видите выше, GetAuthenticationStateAsync() вернется состояние авторизации установлено IHostEnvironmentAuthenticationStateProvider. Итак, вам нужно ввести IHostEnvironmentAuthenticationStateProvider и вызвать IHostEnvironmentAuthenticationStateProvider::SetAuthenticationState(...). И, наконец, состояние аутентификации будет отправлено в Blazor <Authorize/> автоматически.

На самом деле вышеприведенные ServerAuthenticationStateProvider не имеют представления, действителен ли еще участник. Итак, есть еще один встроенный конкретный класс для вас: RevalidatingServerAuthenticationStateProvider.

Приведенный выше код работает для каждой схемы аутентификации, включая ASP. NET Core Identity, JwtBearer, AAD , и так далее. Неважно, какие схемы аутентификации вы используете или какую базу данных используете. Просто расширяет класс RevalidatingServerAuthenticationStateProvider.

Например, если вы используете ASP. NET Core Identity (может возникнуть проблема, связанная с файлами cookie (см. этот поток ), он сгенерирует класс RevalidatingIdentityAuthenticationStateProvider, который использует UserManager<TUser> для проверки допустимости принципала.

public class RevalidatingIdentityAuthenticationStateProvider<TUser>
    : RevalidatingServerAuthenticationStateProvider where TUser : class
{
    ...

    protected override async Task<bool> ValidateAuthenticationStateAsync(
        AuthenticationState authenticationState, CancellationToken cancellationToken)
    {
        // Get the user manager from a new scope to ensure it fetches fresh data
        // use the UserManager to determine whether the current principal is still valid

С тех пор ASP. NET Core Identity не ограничивается SQL Сервером, RevalidatingIdentityAuthenticationStateProvider отлично работает для других баз данных. Если вы хотите использовать MongoDB, не стесняйтесь создавать пользовательские MyMongoDbRevalidatingAuthenticationStateProvider.

Также как бы вы затем использовали это для аутентификации пользователя

Просто объявите компонент следующим образом:

<AuthorizeView>
    <Authorized>
        ...
    </Authorized>
    <NotAuthorized>
       ...
    </NotAuthorized>
</AuthorizeView>

Вы будете НЕ делать это вручную , если вы используете значение по умолчанию RevalidatingServerAuthenticationStateProvider. При использовании Blazor Server Side аутентификация выполняется AuthenticationMiddleware, а затем состояние аутентификации будет передано <AuthorizeView/> автоматически И когда состояние аутентификации истекает, <AuthorizeView/> также будет обновляться автоматически.

навигация Ион в возврате не работает

На самом деле, ваш код должен потерпеть неудачу, прежде чем он перейдет:

HttpContext.SignInAsync(
                CookieAuthenticationDefaults.AuthenticationScheme,
                new ClaimsPrincipal(claimsIdentity));

Обратите внимание, что метод SignIn () попытается отправить повара ie по HTTP. Тем не менее, в большинстве случаев после установления соединения HTTP нет. На самом деле я ответил на один и тот же вопрос несколько месяцев go.


Короче говоря:

  1. Не имеет значения, какую схему аутентификации вы используете, реализуйте RevalidatingServerAuthenticationStateProvider как RevalidatingIdentityAuthenticationStateProvider, если вам нужно.
  2. Если вы используете ASP. NET Core Identity, для вас сгенерировано RevalidatingIdentityAuthenticationStateProvider.
  3. Если вы хотите использовать ASP. NET Core Identity + MongoDB, следуйте официальным документам для реализации такой функции.
  4. Если вы хотите использовать ASP. NET Core Identity + Blazor Server Side, и используйте SignIn (...) для отправки куки, не делайте этого напрямую. Подробнее см. в этой теме .
...