我有一个 ASP.NET Core 2.0 网站,使用普通实现使用 Identity 和 cookie(不使用 OpenID Connect)进行身份验证/授权。我有一组 20 个角色,每个角色可能有数百个声明,用于授予访问网站页面/功能的权限(使用 Authorize 来装饰控制器方法)。我希望能够控制对这些页面/功能的访问,而无需每次需要更改时重新编译网站;相反,我允许管理员直接通过网站添加/删除角色声明。由于某种原因,根据投射到用户身份的声明数量,我达到了上限。
我收到错误消息
HTTP Error 400. The size of the request headers is too long
知道为什么我会收到此消息吗?存储/访问这些经过授权使用的声明的最佳实践是什么?
在 Windows 服务器上遇到同样的问题。 我不得不求助于注册表设置。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters
MaxFieldLength (DWORD) 十进制值 65534
MaxRequestBytes (DWORD) 十进制值 16777216
https://support.microsoft.com/en-ca/help/820129/http-sys-registry-settings-for-windows
此问题可通过配置 CookieAuthenticationOptions 以使用会话存储来解决。 以下链接详细解释了“ASP.NET Core 中的 Auth Cookies”及其配置选项
另一种方法是减少您保存的声明数量,按照为什么声明转换不减少 cookie 大小?.
的答案许多索赔的常见原因是使用 AD 或 AzureAD 或 Entra 身份验证并返回所有用户的安全组。在这种情况下,您可以重新配置应用程序以过滤组或在代码中执行类似的操作:
builder.Services
.AddAuthentication()
.AddCookie(o=>o.Events.OnSigningIn = ctx =>
{
const string groupType = "http://schemas.xmlsoap.org/claims/Group";
var groupsICareAbout = new[]{"Group1", "Group2"};
Predicate<Claim> wantedClaim =
c => c.Type != groupType || groupsICareAbout.Contains(c.Value);
foreach (var identity in ctx.Principal?.Identities ?? [])
{
var unused = identity.FindAll(wantedClaim).ToList();
unused.ForEach(c => identity.TryRemoveClaim(c));
}
return Task.CompletedTask;
});
如果您使用 AD 身份验证,则要使用的事件是
options.Events.OnSecurityTokenReceived
:
builder.Services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
})
.AddWsFederation(options =>
{
options.Wtrealm = builder.Configuration["wsfed:realm"];
options.MetadataAddress = builder.Configuration["wsfed:metadata"];
options.Events.OnSecurityTokenReceived= context =>
{
const string groupType = "http://schemas.xmlsoap.org/claims/Group";
var groupsICareAbout = new[]{"Group1", "Group2"};
Predicate<Claim> wantedClaim =
c => c.Type != groupType || groupsICareAbout.Contains(c.Value);
foreach (var identity in ctx.Principal?.Identities ?? [])
{
var unused = identity.FindAll(wantedClaim).ToList();
unused.ForEach(c => identity.TryRemoveClaim(c));
}
return Task.CompletedTask;
};
})
.AddCookie();