使用非 DefaultAuthenticateScheme 的登录用户提交表单 return HTTP 错误 400
Submit Form return HTTP ERROR 400 for logged in User with non DefaultAuthenticateScheme
我正在构建为不同用户提供多个登录的 MVC 核心应用程序:
- CMS 用户。
- 客户用户
每个用户的类型存储在不同的 sql 服务器 table 中。
由于我使用 不带 ASP.NET 核心身份 的 Cookie 身份验证,因此我创建了以下方案:
- 内容管理系统
- 客户
我已将 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();
});
我正在构建为不同用户提供多个登录的 MVC 核心应用程序:
- CMS 用户。
- 客户用户
每个用户的类型存储在不同的 sql 服务器 table 中。 由于我使用 不带 ASP.NET 核心身份 的 Cookie 身份验证,因此我创建了以下方案:
- 内容管理系统
- 客户
我已将 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();
});