使用 User.IsInRole 会在 UserRole 更改时返回随机结果



我正在使用具有默认身份设置 asp.net 核心 2.1,每次更改角色时,用户都应重新登录以查看角色更改。

如果我添加以下设置,则应在每个请求上更新角色,Authorize属性运行良好,但User.IsInRole()方法在每个请求上返回随机结果。

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

User.IsInRole()有什么问题?如何解决?

编辑: 我对Authorize属性行为不正确,这也是随机的。

编辑:重现问题的测试项目(警告:
它使用的是 InMemory db(-> https://github.com/ans-ashkan/AspNetCoreUserIsInRoleTest

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"}

编辑: AspNet/MVC 存储库上的问题链接

我已经详细调查了这个问题,并在这个问题中发布了我的发现。这确实是一个错误,但它实际上对您的问题没有太大影响:

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

但是,在我看来,您完全滥用了这一点:如果您想在每个请求上刷新标识及其声明,那么实际上根本没有任何意义。运行身份验证堆栈不是免费的,并且必须运行验证和重新颁发的整个管道将非常昂贵。当你实际上不想将身份存储更长的时间时(因为你在下一个请求中使它无效(,那么这真的是浪费工作。

因此,如果您真的需要一个绝对清晰且在它们发生变化时立即更新的权限系统,请考虑使用不同的东西。您可以设置一个单独的数据库,并将"角色"存储在那里,然后,当您访问受保护的内容时,您只需按需获取用户的角色以验证访问权限。这也将帮助您在每个请求上始终获取角色,因为现在您只会在需要时获取它。

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

实际上,您可以使用 ASP.NET Core的授权堆栈很好地设计它。例如,您可以为角色创建要求,然后实现通过数据库检查角色的授权处理程序。这样,就可以使此操作像对用户使用角色声明一样透明。例如,您可以只使用与否则相同的Authorize属性。

最新更新