我正在处理声明基础身份验证,它运行正常。 现在我想添加角色自动化。 我有用户的角色声明(例如“Admin”)
调用IsInRole()方法时,会检查是否存在 当前用户具有该角色。在声明感知应用程序中,角色 由角色声明类型表示,该类型应该在 令牌。角色声明类型使用以下URI表示: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
//Include all claims
//claims is List<Claim> with all claims
var id = new ClaimsIdentity(claims, "Cookies");
Request.GetOwinContext().Authentication.SignIn(id);
如果我检查用户是否在角色中,我会得到错误。虽然我的角色声明带有“管理员”值
User.IsInRole("Admin");
同时授权我的api上的attrubute不起作用
[Authorize (Roles = "Admin")]
我可能误解了如何让角色对用户可见。可能只是将Roles列入索赔列表中呢?
答案 0 :(得分:11)
如果您的服务使用的是Windows身份验证,则您收到的IPrincipal.Identity
类型为WindowsPrincipal
。这有点误导,但ClaimType
寻找的WindowsPrincipal.IsInRole()
不是ClaimTypes.Role
,正如您可能合理预期的那样,而是ClaimTypes.GroupSid
。
但是,您不应该假设当前Identity用于指定角色的实际ClaimType,因为不同类型的标识使用不同的值。相反,您应该引用ClaimsIdentity.RoleClaimType
属性。
我们在以下几行中实施了IAuthenticationFilter
:
public Task AuthenticateAsync(HttpAuthenticationContext context, cancellationToken)
{
var principal = context.Principal;
if(principal.Identity is ClaimsIdentity && principal.Identity.IsAuthenticated)
{
var ci = (ClaimsIdentity)principal.Identity;
// get the user's additional roles from somewhere and add Claims
ci.AddClaim(new Claim(ci.RoleClaimType, "MyRole"));
}
}
这允许我们在ASP.Net控制器中使用标准的AuthorizeAttribute机制。 e.g。
[Authorize(Roles="MyRole")]
public IHttpActionResult Get()
{
//authenticated and authorised code here
}
有关进一步说明,请参阅MSDN上的ClaimsIdentity.RoleClaimType。
请注意:将用户定义的角色添加到WindowsPrincipal
可能会导致问题。似乎.Net Framework 4.5的当前实现(截至2017年4月)在检查角色时有时会抛出异常,期望从Active Directory获得角色的详细信息。有关替代方法,请参阅this question。
答案 1 :(得分:3)
可能声明的ClaimType只是“角色”。
您应该使用Microsoft Schema创建声明:
manager.AddClaim(dn1.Id, claim: new Claim(ClaimTypes.Role.ToString(), "ADMINISTRATOR"));
然后User.IsInRole("Admin");
和[Authorize (Roles = "Admin")]
将正常运作。
这是因为Microsoft Identity使用架构:
http://schemas.microsoft.com/ws/2008/06/identity/claims/role
何时进行角色检查。 我建议你检查ASPNETIdentity数据库,以便全面了解如何插入che声明。 我很确定AspNetUserClaims的ClaimType与Microsoft Schema不同。
此致
答案 2 :(得分:2)
TL; DR案例敏感度,也许?
我发现默认使用的检查是......
[Authorize(Roles = "RoleA,RoleB")]
......区分大小写。
我在大小写混合的情况下创建了角色,并使用了AspNetCore的Identity Manager,并使用非EF内存实现进行测试。
UserManager.IsInRole(&#34; RoleA&#34;)返回true,但是当通过ClaimsPrincipal检查时,HttpContext.User.IsInRole(&#34; RoleA&#34;)返回false。我将声明转发给文本,并且可以看到有正确的MS模式的角色声明...
ClaimType:[http://schemas.microsoft.com/ws/2008/06/identity/claims/role], ClaimValue:[ROLEA], Issuer:[TokenServer]
ClaimType:[http://schemas.microsoft.com/ws/2008/06/identity/claims/role], ClaimValue:[ROLEB], Issuer:[TokenServer]
...但是索赔价值(角色)是大写的 要解决这个问题,我只需将属性更改为...
[Authorize(Roles = "ROLEA,ROLEB")]
......它有效。
因此,如果您在让角色授权在AspNetCore中工作时遇到问题,请尝试阅读声明,并完全匹配声明。您可以通过访问HttpContext.User.Claims对象来阅读声明...
foreach (var claim in HttpContext.User.Claims)
Console.WriteLine($"ClaimType:[{claim.Type}], ClaimValue:[{claim.Value}], Issuer:[{claim.Issuer}]");
当然可能是我以某种方式将角色编码为大写字母,或者某处使用了NormalisedRole,但你可能做了同样的事情......
答案 3 :(得分:0)
您没有提到正在使用哪种身份验证方法,但是,如果您使用的是JWT身份验证,则需要在生成令牌时将角色添加到ClaimsIdentity中,如本博文所述:ASP.NET Core JWT mapping role claims to ClaimsIdentity >
答案 4 :(得分:0)
请注意 HttpContext.User.Identity.RoleClaimType: “角色”
可能与 ClaimTypes.Role = “ http://schemas.microsoft.com/ws/2008/06/identity/claims/role”
因此,在生成声明标识时,您可能需要使用“角色”作为键而不是ClaimTypes常量来添加声明。 ClaimsIdentity.IsInRole(String)使用ClaimsIdentity.RoleClaimType定义的声明密钥。
我的工厂代码看起来像这样...
var identity = await base.GenerateClaimsAsync(user);
var roles = await UserManager.GetRolesAsync(user);
foreach (var role in roles)
{
identity.AddClaim(new Claim(ClaimTypes.Role, role));
identity.AddClaim(new Claim("role", role));
}
return identity;
第一个添加确实是多余的,但让我觉得我实际上是在添加正确的声明。