【问题标题】:Anti-Forgery Token Validation in MVC app with Blazor Server-side Component使用 Blazor 服务器端组件的 MVC 应用程序中的防伪令牌验证
【发布时间】:2020-03-26 01:14:47
【问题描述】:

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

Microsoft.AspNetCore.Mvc.Infrastructure.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>

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

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

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

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

即使我的退出案例不是什么大威胁,调用任何其他类似注释的操作也是如此。

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

【问题讨论】:

  • github.com/aspnet/AspNetCore/issues/11787 - CSRF 令牌不涉及服务器端 Blazor 电路,因为 CSRF 旨在防止意外的第三方 HTTP 请求,而服务器端 Blazor 电路存在于 WebSocket 中连接。
  • @Dennis1679,谢谢。在这种情况下这意味着什么?我应该从动作中删除注释吗?这不会使该行动变得脆弱吗?它仍然是 MVC 应用程序。
  • 你知道,当 Steve Sanderson(.net 团队的成员)说 CSRF 不是问题时,他可以信任他。但是,在阅读了 Microsoft 的安全部分后,似乎甚至可以创建恶意 WebSocket。 docs.microsoft.com/en-us/aspnet/core/security/blazor/…

标签: c# asp.net-core asp.net-core-mvc blazor blazor-server-side


【解决方案1】:

我一直在尝试让防伪功能为 Logout POST 工作。我想我只是设法让它工作。我愿意接受改进建议!

我在Blazor Server additional security scenarios 上使用了一个 MS 文档,它解释了一种存储 OIDC 访问和刷新令牌以在 Blazor 组件中使用的方法。我修改了该示例,以便以类似的方式使用防伪令牌,如下所示:

  1. 我创建了一个TokenProvider 类来存储防伪令牌。
public class TokenProvider
{
    public string AntiforgeryToken { get; set; }
}
  1. Startup.ConfigureServices() 中向 DI 添加了 Scoped TokenProvider
public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddScoped<TokenProvider>();
    ...
}
  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" />
...
  1. App.razor 然后在 OnInitializedAsync() 期间填充 TokenProvider
@inject TokenProvider tokenProvider

<Router ....
</Router>

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

    protected override Task OnInitializedAsync()
    {
        tokenProvider.AntiforgeryToken = AntiforgeryToken;
        return base.OnInitializedAsync();
    }
}
  1. TokenProvider 然后可以通过在我的Logout.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>
...

【讨论】:

    【解决方案2】:

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

       @Html.AntiForgeryToken()
    </body>
    

    【讨论】:

      猜你喜欢
      • 2015-08-15
      • 1970-01-01
      • 2014-01-23
      • 2021-10-03
      • 2011-07-21
      • 2020-12-03
      • 2018-07-09
      • 2020-10-13
      • 2013-10-28
      相关资源
      最近更新 更多