我使用具有默认身份设置的asp.net core 2.1,每次更改角色时,用户都应重新登录以查看角色更改。
如果我添加以下设置,则应在每个请求上更新角色, ,但是Authorize
属性可以很好地发挥作用User.IsInRole()
方法将在每个请求上返回随机结果。>
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"}
答案 0 :(得分:2)
我已经posted my findings in the issue详细调查了这个问题。这确实是一个错误,但实际上对您的问题没有太大影响:
更改用户的角色不会使用户的安全印章无效,因此用户通过Cookie收到的已发布的声明身份实际上并不是无效的。因此,如果要在角色更改时使身份失效,则必须寻找其他解决方案。
但是,在我看来,您完全误用了这一点:如果您要针对每个单个请求刷新身份及其声明,那么实际上没有必要在此处拥有声明身份所有。运行身份验证堆栈不是免费的,并且必须运行整个验证和重新发布管道将非常昂贵。而且,如果您实际上根本不想长时间保存 身份(因为您在下一个请求中将其无效),那真是浪费了工作。
因此,如果您确实需要一个绝对敏锐且在更改时即刻进行更新的权限系统,请考虑使用其他功能。您可以建立一个单独的数据库,然后在其中存储“角色”,然后,当您访问受保护的内容时,只需按需获取用户的角色即可验证访问权限。这也将帮助您始终在每个请求上都获取角色,因为现在仅在需要时才获取它。
当然,您不需要 为此单独的数据库。您还可以使用身份的内置角色。然后,您只需要记住角色 claims 并不总是事实的来源,因此您应该始终从数据库(通过用户管理器)加载用户的角色。
实际上,您可以使用ASP.NET Core的authorization stack进行出色的设计。例如,您可以创建一个角色需求,然后实现一个授权处理程序,该处理程序通过检查数据库来检查角色。这样,您就可以像对用户使用角色声明一样透明。例如。您可以只使用与其他情况下相同的Authorize
属性。