如何使用Blazor服务器对用户进行身份验证

时间:2020-02-24 20:40:30

标签: c# mongodb authentication asp.net-core blazor

我有一个Blazor Server应用程序,该应用程序使用MongoDB作为数据库,因此我正在尝试实现身份验证。因此,我可以在剃须刀页面中使用operation = int((input("""Operations?: 1: Add 2: Substract 3: Multiply 4: Divide """))) num1 = int(input("Enter first number: ")) num2 = int(input("Enter second number: ")) maths = Math(num1,num2) 和其他标签。

内置的身份验证模板使用SQL Server,在这种情况下我不希望使用SQL Server,并且没有明确的示例说明如何使用其他数据库自己进行操作。给定示例,Microsoft提供了here

<Authenticted>, <AuthorizeView Roles="admin">

一个人应该如何在应用程序中使用它?显然,您不会硬编码单个值和值类型作为唯一的身份验证来源。那么应该如何对其进行参数化?具有以下本地属性:

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(...)

我不知道如何对任何人进行身份验证。我想您会以多种方式验证用户名和密码,然后当您知道这很好时,就可以继续在.NET中更新身份验证。我在跟随一个教程,他们在后面的代码中提出了类似的建议:

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

但是,返回中的导航不起作用(它们甚至都没有解释他们的代码是如何编译的),并且SignInAsync()方法无法以它们显示的方式使用。同样,我不知道他们的代码如何编译。那么,通常情况下该怎么做?

除数百个仅使用内置SQL Server模板的 之外,我找不到任何教程,示例等。在哪里可以找到有关如何使用它的详细信息?除了“使用内置模板”或指向文档{{3}}的链接以外的任何内容,都无法解释为怎么做。

1 个答案:

答案 0 :(得分:10)

内置的身份验证模板使用SQL Server,在这种情况下我不希望这样做,并且没有明确的示例说明如何使用其他数据库自己进行操作

我猜您正在使用ASP.NET Core 身份,对吗?如果您正在寻找一种使用其他提供程序的方式,请参见official docs

一个人应该如何在应用程序中使用它?显然,您不会硬编码单个值和值类型作为唯一的身份验证来源。那么应该如何对其进行参数化?

由于使用的是Blazor服务器(而不是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身份,JwtBearer,AAD等。使用哪种身份验证方案或使用哪个数据库都没有关系。只需扩展RevalidatingServerAuthenticationStateProvider类。

例如,如果您使用的是ASP.NET Core 身份(您可能会看到与Cookies相关的问题(请参见this thread),它将生成一个{{ 1}}使用RevalidatingIdentityAuthenticationStateProvider来验证主体是否有效。

UserManager<TUser>

由于 ASP.NET Core身份不仅限于SQL Server,因此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 对于其他数据库也可以正常工作。如果要使用MongoDB,请随时创建自定义RevalidatingIdentityAuthenticationStateProvider

然后您将如何使用它来验证用户身份

只需这样声明组件:

MyMongoDbRevalidatingAuthenticationStateProvider

如果您使用默认的<AuthorizeView> <Authorized> ... </Authorized> <NotAuthorized> ... </NotAuthorized> </AuthorizeView> ,您将 手动进行操作。使用Blazor服务器端,身份验证由RevalidatingServerAuthenticationStateProvider完成,然后身份验证状态将自动传递到AuthenticationMiddleware 。并且当身份验证状态过期时,<AuthorizeView/>也将自动更新。

返回中的导航不起作用

实际上,您的代码在导航之前应该会失败:

<AuthorizeView/>

请注意,SignIn()方法将尝试通过HTTP发送Cookie。但是,大多数情况下,连接建立后没有HTTP。其实我有answered an exactly same question several month ago


简而言之:

  1. 使用哪种身份验证方案都没关系,如果需要,可以像HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); 一样实现RevalidatingServerAuthenticationStateProvider
  2. 如果您使用的是ASP.NET Core身份,则会为您生成一个RevalidatingIdentityAuthenticationStateProvider
  3. 如果要使用ASP.NET Core Identity + MongoDB,请按照official docs来实现此功能。
  4. 如果要使用ASP.NET Core身份+ Blazor服务器端,并使用SignIn(...)发送Cookie,请不要直接执行此操作。有关更多详细信息,请参见this thread