具有角色的授权属性是否考虑了声明
does Authorize attribute with Roles take Claims into account
我在网上到处搜索,但我似乎无法弄清楚这个重要部分。
基本上,如果我们每次检查用户是否属于某个角色时都调用数据库 - 这会对性能产生负面影响。
我看到了列出所有用户角色的代码示例,例如
var roles = ((ClaimsIdentity)User.Identity).Claims
.Where(c => c.Type == ClaimTypes.Role)
.Select(c => c.Value);
代码可用于控制器操作,也可以在属性过滤器中以相同方式获取声明。
从这个例子中我推断 Claims
发挥作用(似乎是最高效的解决方案)。
我试图找出 if Authorize
具有角色的属性验证用户的声明,但是 official Microsoft documentation不包括这一点。
AuthorizeAttribute
class
Specifies that access to a controller or action method is restricted to users who meet the authorization requirement.
Properties:
Roles
- Gets or sets the user roles that are authorized to access the controller or action method.
这就是我们所拥有的范围。
打开您的启动文件并将其更改为:
services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
对此:
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI()
.AddDefaultTokenProviders();
然后角色应该开始工作了。
授权属性,例如User.IsInRole 查看 User.Identity 角色声明。
默认情况下,权限(用户登录的地方)将添加来自 AspNetUserRoles table 的角色作为类型“http://schemas.microsoft.com/ws/2008/06/identity/claims/role
”的声明。参见 WIF claimtypes members。
客户端应用程序将自动从令牌/cookie 中获取信息并将其转换为 User.Identity。当声明类型匹配时,角色类型声明将映射为角色。
这意味着该应用不需要访问用户存储。在大多数情况下,这也是不可能的。所以它实际上不是关于性能,而是关于可访问性。通常应用程序无权访问身份上下文。所以 UserManager 不是一个选项。
然而,使用声明时有一个缺点。该信息已过时。当用户登录时,声明当时的快照被添加到身份中。如果同时声明(或角色)在数据库中更新,则不会记录这些更改。只有用户重新登录后,修改才会生效。
这意味着声明仅适用于 table 不(经常)更改的信息,除非您找到使声明无效的方法。但这可能意味着访问数据库或调用权限。
这就是我不推荐使用角色的原因。由于角色往往用于授权,但您不能同时撤销访问权限。因此,在您解决该问题之前,您可能需要考虑替代方案。
坚持使用 UserManager 不是替代方案,因为上下文可能不适用于所有应用程序。
这就是为什么基于资源的授权可能是适合您的解决方案。请阅读我的回答 以了解更多想法。
我在网上到处搜索,但我似乎无法弄清楚这个重要部分。
基本上,如果我们每次检查用户是否属于某个角色时都调用数据库 - 这会对性能产生负面影响。
我看到了列出所有用户角色的代码示例,例如
var roles = ((ClaimsIdentity)User.Identity).Claims
.Where(c => c.Type == ClaimTypes.Role)
.Select(c => c.Value);
代码可用于控制器操作,也可以在属性过滤器中以相同方式获取声明。
从这个例子中我推断 Claims
发挥作用(似乎是最高效的解决方案)。
我试图找出 if Authorize
具有角色的属性验证用户的声明,但是 official Microsoft documentation不包括这一点。
AuthorizeAttribute
classSpecifies that access to a controller or action method is restricted to users who meet the authorization requirement.
Properties:
Roles
- Gets or sets the user roles that are authorized to access the controller or action method.
这就是我们所拥有的范围。
打开您的启动文件并将其更改为:
services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
对此:
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI()
.AddDefaultTokenProviders();
然后角色应该开始工作了。
授权属性,例如User.IsInRole 查看 User.Identity 角色声明。
默认情况下,权限(用户登录的地方)将添加来自 AspNetUserRoles table 的角色作为类型“http://schemas.microsoft.com/ws/2008/06/identity/claims/role
”的声明。参见 WIF claimtypes members。
客户端应用程序将自动从令牌/cookie 中获取信息并将其转换为 User.Identity。当声明类型匹配时,角色类型声明将映射为角色。
这意味着该应用不需要访问用户存储。在大多数情况下,这也是不可能的。所以它实际上不是关于性能,而是关于可访问性。通常应用程序无权访问身份上下文。所以 UserManager 不是一个选项。
然而,使用声明时有一个缺点。该信息已过时。当用户登录时,声明当时的快照被添加到身份中。如果同时声明(或角色)在数据库中更新,则不会记录这些更改。只有用户重新登录后,修改才会生效。
这意味着声明仅适用于 table 不(经常)更改的信息,除非您找到使声明无效的方法。但这可能意味着访问数据库或调用权限。
这就是我不推荐使用角色的原因。由于角色往往用于授权,但您不能同时撤销访问权限。因此,在您解决该问题之前,您可能需要考虑替代方案。
坚持使用 UserManager 不是替代方案,因为上下文可能不适用于所有应用程序。
这就是为什么基于资源的授权可能是适合您的解决方案。请阅读我的回答