使用 Blazor 服务器端组件在 MVC 应用程序中进行防伪造令牌验证

Gia*_*rra 8 c# asp.net-core-mvc asp.net-core blazor blazor-server-side

随着 ASP.NET Core 3.0 的推出,我尝试在 MVC Core 应用程序中利用服务器端 Blazor 功能。我首先创建一个简单的导航组件,尝试让用户使用指向控制器操作的按钮退出。但是,我遇到了防伪造令牌验证错误,内容如下:

Microsoft.AspNetCore.Mvc.Infrastruct.ControllerActionInvoker:信息:过滤器“Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.ValidateAntiforgeryTokenAuthorizationFilter”处的请求授权失败。

然后服务器返回 HTTP 400 状态代码。

我正在遵循 Blazor 应用程序模板代码(带有 Visual Studio 2019 的 Blazor 版本 0.7.0):

<AuthorizeView>
    <Authorized>
        <a href="/Account/Manage">Hello, @context.User.Identity.Name!</a>
        <form method="post" action="/Account/Logout">
            <button type="submit">Sign out</button>
        </form>
    </Authorized>
    <NotAuthorized>
        <a href="/Account/Register">Register</a>
        <a href="/Account/Login">Log in</a>
    </NotAuthorized>
</AuthorizeView>
Run Code Online (Sandbox Code Playgroud)

我的 MVCAccount控制器有一个带有 注释的注销操作[ValidateAntiForgeryToken],如下所示:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout()
{
    await _signInManager.SignOutAsync();
    _logger.LogInformation("User logged out.");
    return RedirectToAction(nameof(HomeController.Index), "Home");
}
Run Code Online (Sandbox Code Playgroud)

过去,我会@Html.AntiForgeryToken()在表单中添加一个以符合我注释的注销操作。在较新版本的 ASP.NET Core 中,您不再需要手动添加它,因为它包含在表单标记帮助程序中。但这两种方法似乎都无法在 Blazor 组件中转换或可用。

如何从 Blazor 组件调用此 MVC 操作并为控制器验证提供防伪令牌?或者根本不再需要这种验证?

即使我的退出案例不是一个大威胁,这对于调用类似注释的任何其他操作也是一样的。

我可能缺少一个适用于混合 MVC 和 Blazor 场景的 CSRF 技术概念。

Rob*_*Rob 14

我一直在尝试让防伪功能适用于注销帖子。我想我刚刚成功让它发挥作用。我愿意接受改进建议!

我在Blazor Server 附加安全方案中使用了 MS 文档,该文档解释了存储 OIDC 访问和刷新令牌以便在 Blazor 组件中使用的方法。我修改了该示例,以便以类似的方式使用防伪令牌,如下所示:

  1. 我创建了一个TokenProvider类来存储防伪令牌。
public class TokenProvider
{
    public string AntiforgeryToken { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
  1. 添加了一个 ScopedTokenProvider到 DI 中Startup.ConfigureServices()
public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddScoped<TokenProvider>();
    ...
}
Run Code Online (Sandbox Code Playgroud)
  1. 获取防伪令牌_Host.cshtml并将其作为参数传递给我的App组件
@page "/"
@namespace My.Pages
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery antiforgery
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

@{
    var token = antiforgery.GetAndStoreTokens(HttpContext).RequestToken;
}
...
<body>
  <component type="typeof(App)" render-mode="ServerPrerendered" param-AntiforgeryToken="token" />
...
Run Code Online (Sandbox Code Playgroud)
  1. App.razor然后填充TokenProvider期间OnInitializedAsync()
@inject TokenProvider tokenProvider

<Router ....
</Router>

@code {
    [Parameter]
    public string AntiforgeryToken { get; set; }

    protected override Task OnInitializedAsync()
    {
        tokenProvider.AntiforgeryToken = AntiforgeryToken;
        return base.OnInitializedAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. TokenProviderLogout.razor然后可以通过在我的组件中注入来使用
@inject TokenProvider tokenProvider
...
<form method="post" action="Logout">
    <input name="__RequestVerificationToken" type="hidden" value="@tokenProvider.AntiforgeryToken">
    <button type="submit" class="nav-link btn btn-link" title="Log out">
        <span class="oi oi-account-logout"></span>
    </button>
</form>
...
Run Code Online (Sandbox Code Playgroud)


Mar*_*ijk 1

不知道为什么会弹出这个异常。但这对我有用。只需将其添加到 _Host.cshtml 文件的末尾即可。

   @Html.AntiForgeryToken()
</body>
Run Code Online (Sandbox Code Playgroud)