当 UserRole 改变时使用 User.IsInRole returns 随机结果

Using User.IsInRole returns random result when UserRole changes

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

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

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

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

编辑: 我对 Authorize 属性行为的理解是错误的,它也是随机的。

编辑:
重现问题的测试项目(警告:它正在使用 InMemory 数据库)-> 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"}

编辑: Issue link on AspNet/MVC repo

我已经详细调查了这个问题 posted my findings in the issue。这确实是一个错误,但实际上对你的问题影响不大:

更改用户的角色不会使用户的安全标记失效,因此用户通过 cookie 收到的已发布声明身份实际上并不是无效的。所以如果你想在角色改变时使身份失效,你将不得不寻找不同的解决方案。

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

因此,如果您真的需要一个绝对敏锐且在更改时立即更新的权限系统,请考虑使用不同的东西。你可以建立一个单独的数据库,只把“角色”存储在那里,然后,当你访问受保护的东西时,你只需在那里按需获取用户的角色来验证访问。这也将帮助您在每次请求时始终获取角色,因为现在您只会在需要时获取它。

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

你实际上可以用 ASP.NET Core 的 authorization stack 设计得很好。例如,您可以为一个角色创建一个要求,然后实现一个授权处理程序,该处理程序通过遍历数据库来检查该角色。这样,您就可以像使用用户角色声明一样透明。例如。您可以只使用与其他方式相同的 Authorize 属性。