是的,在您的 Razor 页面中添加按钮是可能的。
当然,要做到这一点,您需要能够枚举可用的提供程序,这意味着您需要从 _Host.cshtml(或您托管 Blazor 应用程序的任何位置)将它们传递给您的 Blazor 应用程序。
注意:您无法传递 AuthenticationScheme
列表,因为 .NET 不会序列化它们,这就是为什么我将它们转换为 DTO ExternalProvider
的原因。
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@inject SignInManager<IdentityUser> _signInManager
@{
var state = new InitialApplicationState
{
XsrfToken = Xsrf.GetAndStoreTokens(HttpContext).RequestToken,
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
.ToList()
.Select(scheme=>
new ExternalProvider {Name=scheme.Name, DisplayName=scheme.DisplayName}
)
};
}
<component type="typeof(App)" param-InitialState="state" render-mode="ServerPrerendered" />
InitialApplicationState
和ExternalProvider
是简单的数据传输对象类。
public class InitialApplicationState
{
public string XsrfToken { get; set; }
public IEnumerable<ExternalProvider> ExternalLogins { get; set; }
}
public class ExternalProvider
{
public string Name { get; set; }
public string DisplayName { get; set; }
}
现在,您需要在App.razor
组件上将此数据作为Parameter
接收到您的Blazor代码中
@inject InitialApplicationState InitialStateService
@code {
[Parameter] public InitialApplicationState InitialState { get; set; } = default;
protected override Task OnInitializedAsync()
{
InitialStateService.XsrfToken = InitialState.XsrfToken;
InitialStateService.ExternalLogins = InitialState.ExternalLogins;
return base.OnInitializedAsync();
}
}
我们所做的只是声明一个参数
InitialState
,它将接收我们的
InitialApplicationState
- 然后我们将该状态存储在一个服务
InitialStateService
中,该服务在
startup.cs
中配置为Scoped依赖项。
builder.Services.AddScoped<InitialApplicationState>();
现在,我们在DI容器中有一个服务,用于Blazor,其中包含可用的外部身份验证提供程序列表和我们的伪造保护令牌。
我们可以在Blazor中的任何需要它的地方注入
InitialApplicationState
,例如
Index.razor
,并枚举
ExternalLogins
以渲染按钮。
在Blazor中,表单的声明略有不同,因为我们没有
asp*
指令:
@inject InitialApplicationState InitialStateService
<form id="external-account"
action="/Identity/Account/ExternalLogin"
method="post">
<div>
<p>
@foreach (var provider in InitialStateService.ExternalLogins)
{
<button type="submit"
name="provider"
value="@provider.Name"
title="Log in using your @provider.DisplayName account">
@provider.DisplayName
</button>
}
</p>
</div>
<input name="__RequestVerificationToken" type="hidden"
value="@InitialStateService.XsrfToken">
</form>