使用非 DefaultAuthenticateScheme 的登录用户提交表单 return HTTP 错误 400

Submit Form return HTTP ERROR 400 for logged in User with non DefaultAuthenticateScheme

我正在构建为不同用户提供多个登录的 MVC 核心应用程序:

  1. CMS 用户。
  2. 客户用户

每个用户的类型存储在不同的 sql 服务器 table 中。 由于我使用 不带 ASP.NET 核心身份 的 Cookie 身份验证,因此我创建了以下方案:

  1. 内容管理系统
  2. 客户

我已将 Startup.cs 文件中的方案注册为:

public void ConfigureServices(IServiceCollection services)
{
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    services.AddAuthentication("CMS")
        .AddCookie("CMS", o => { o.LoginPath = "/CMS/Login"; })
        .AddCookie("Client", o => { o.LoginPath = "/Client/Login"; });

    services.AddControllersWithViews();
}

我根据需要用它的 shceme 和必需的角色装饰了控制器操作:

[Authorize(AuthenticationSchemes = "Client", Roles = "AdminRole")]

某些操作未使用授权修饰,因为所有用户(已登录或已注销)都使用它们。

问题: 当任何类型的用户(CMS 或客户端,无论他们是否登录)尝试提交一个简单的表单时:

<form action="/Home/Search" method="post">
  <div class="input-group">
     @Html.AntiForgeryToken();
      <input type="text" class="form-control" name="Search"  value="">
      <button type="submit">Search</button>
  </div>
</form>

目标操作是:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Search(SearchViewModel vm)
{
    vm.Results = ""; //Do some work
    return View("Search", vm);
}

只有 CMSUsers 设法达到目标操作,因为 CMS 方案默认方案 在 Startup.cs:

中注册
    services.AddAuthentication("CMS")
        .AddCookie("CMS", o => { o.LoginPath = "/CMS/Login"; })
        .AddCookie("Client", o => { o.LoginPath = "/Client/Login"; });

如果我将默认方案更改为客户端,只有客户端方案能够成功调用目标操作,CMS 将收到错误 400。

此外,如果我从目标操作中删除 [ValidateAntiForgeryToken],所有用户都可以成功提交表单。

我错过了什么?

还是单方案认证?

在网上搜索后,在 Startup.cs 中添加以下内容解决了问题。

    app.Use(async (context, next) =>
    {
        var principal = new ClaimsPrincipal();
        var result1 = await context.AuthenticateAsync("CMS");
        if (result1?.Principal != null)
        {
            principal.AddIdentities(result1.Principal.Identities);
        }

        var result2 = await context.AuthenticateAsync("Client");
        if (result2?.Principal != null)
        {
            principal.AddIdentities(result2.Principal.Identities);
        }

        context.User = principal;
        await next();
    });