Asp.net core 当用户角色更改时,使用User.IsInRole将返回随机结果

Asp.net core 当用户角色更改时,使用User.IsInRole将返回随机结果,asp.net-core,asp.net-core-identity,Asp.net Core,Asp.net Core Identity,我使用的是asp.net core 2.1,具有默认身份设置,每次角色更改时,用户都应该重新登录以查看角色更改 如果我添加以下设置,每个请求都应该更新角色,Authorize属性工作正常,但是User.IsInRole()方法会在每个请求上返回随机结果 services.Configure<SecurityStampValidatorOptions>(options => { options.ValidationInterval = TimeSpan.Zero; })

我使用的是asp.net core 2.1,具有默认身份设置,每次角色更改时,用户都应该重新登录以查看角色更改

如果我添加以下设置,每个请求都应该更新角色,
Authorize
属性工作正常,但是
User.IsInRole()
方法会在每个请求上返回随机结果

services.Configure<SecurityStampValidatorOptions>(options =>
{
     options.ValidationInterval = TimeSpan.Zero;
});
编辑:

我已经详细地调查了这个问题,并对其进行了分析。这确实是一个bug,但实际上对您的问题没有多大影响:

更改用户的角色不会使用户的安全戳无效,因此用户通过cookie接收的已发布声明标识实际上并不无效。因此,如果要在角色更改时使标识无效,则必须寻找不同的解决方案

然而,在我看来,您完全误用了这一点:如果您希望在每个请求中刷新标识及其声明,那么实际上拥有声明标识是毫无意义的。运行身份验证堆栈不是免费的,而且必须运行整个验证和重新发布管道将非常昂贵。而且,如果您实际上不想将标识存储更长的时间(因为您在下一个请求中就将其作废),那么这真的是浪费工作

<>如果你真的需要一个绝对锐利的权限系统,当他们改变的时候马上更新,然后考虑使用不同的东西。您可以设置一个单独的数据库,只需将“角色”存储在那里,然后,当您访问受保护的内容时,只需在那里按需获取用户的角色以验证访问。这也将帮助您在每次请求时始终获取角色,因为现在您只能在需要时获取角色

当然,这不需要单独的数据库。您还可以使用Identity的内置角色。您只需要记住,角色声明并不总是事实的来源,因此您应该始终从数据库(通过用户管理器)加载用户的角色


实际上,您可以使用ASP.NET内核很好地设计它。例如,您可以为角色创建一个需求,然后实现一个授权处理程序,通过遍历数据库检查角色。通过这种方式,您可以使其与使用用户角色声明一样透明。例如,您可以只使用与其他情况相同的
Authorize
属性。

当您说random时,您的意思是更改的角色只是偶尔使用吗?你可以尝试连接并确认它被调用。随机我的意思是,在我多次刷新页面时更改某些角色(仅一次)后,有时会显示角色更改,但有时不会。我怎样才能参加那个活动?如果是通过使用
services.AddAuthentication().AddCookie
进行的,则不会触发该操作。但是SecurityStampValidator
OnRefreshingPrincipal
每次都会被解雇。这种行为很奇怪,出于兴趣,
User.Identity.Name
在角色检查时每次都显示什么?如果该事件没有触发,则可能会将
ValidationInterval
设置为除
TimeSpan.Zero
之外的值,然后重试?很抱歉,回答太晚了,我测试的ValidationInterval超过了零,我得到了相同的结果,还检查了
User.Identity.Name
的值,它正确返回用户名。@MarkG另外,我已经用指向简单项目的链接更新了问题,以重现问题
http://localhost:5000/users/getall -> 200: ["test"]
http://localhost:5000/users/signin?username=test&password=123 -> 200
http://localhost:5000/users/isinrole?role=admin -> {"isInRole":false,"identityName":"test"}
http://localhost:5000/users/adduserrole?username=test&role=admin -> 200
http://localhost:5000/users/isinrole?role=admin -> {"isInRole":**random true or false**,"identityName":"test"}
http://localhost:5000/users/signout -> 200
http://localhost:5000/users/signin?username=test&password=123 -> 200
http://localhost:5000/users/isinrole?role=admin -> {"isInRole":true,"identityName":"test"}