我已经创建了一个自定义的 IClaimsTransformation 类,它从配置文件中获取允许组的列表。如果用户在其中一个组中,则添加声明。我可以验证声明是否已添加,但用户仍然无法访问该页面。如果我用组名修饰 Authorize 属性,它会起作用,但如果我用我的自定义角色修饰它,如果用户属于配置文件中的组之一,它就不起作用。
public class ClaimsTransformer : IClaimsTransformation
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
PowerConfig.Initialize();
var ci = (ClaimsIdentity)principal.Identity;
var re = ci.Claims.Where(x => x.Type == ClaimTypes.GroupSid || x.Type == ClaimTypes.PrimaryGroupSid).ToList();
foreach (var item in re)
{
string account = new System.Security.Principal.SecurityIdentifier(item.Value).Translate(typeof(System.Security.Principal.NTAccount)).ToString();
var roleClaim = new Claim(ClaimTypes.Role, account);
ci.AddClaim(roleClaim);
foreach (var group in PowerConfig.ServerSettings.Authorization.ForwardsList)
{
if (account == group)
{
ci.AddClaim(new Claim(ClaimTypes.Role, "Forwards"));
}
}
foreach (var group in PowerConfig.ServerSettings.Authorization.ScheduledForwardsList)
{
if (account == group)
{
ci.AddClaim(new Claim(ClaimTypes.Role, "ScheduledForwards"));
}
}
}
return Task.FromResult(principal);
}
}
这有效(使用实际的组名):
@page "/forwards"
@attribute [Authorize(Roles = "POWERSOURCE\\PowerSource Admins")]
主动前锋
这行不通
@page "/forwards"
@attribute [Authorize(Roles = "Forwards")]
但是,如果我在转换类的返回结果上设置断点,我可以看到声明“Forwards”已添加到确实有效的角色 PowerSource Admins 旁边。 (见下文)
我之所以这样设置是因为我不想将允许访问该页面的组硬编码到代码中。我认为最好对自定义角色进行硬编码,然后根据设置为属于正确组的用户授予该角色。如果有更好的方法,请告诉我。
另外,claimstransformer 类运行了 4 次。我认为这是设计使然,但我只是想知道为什么会这样。
更新:
有人在我耳边低声说要尝试一个新的身份而不是更新 Windows 身份。我试过了,它奏效了。我不明白为什么它以前不起作用,因为所有其他角色都是通过修改 Windows 身份添加的。哦,下面的代码有效。
public class ClaimsTransformer : IClaimsTransformation
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
PowerConfig.Initialize();
var ci = (ClaimsIdentity)principal.Identity;
var ci2 = new ClaimsIdentity();
var re = ci.Claims.Where(x => x.Type == ClaimTypes.GroupSid || x.Type == ClaimTypes.PrimaryGroupSid).ToList();
foreach (var item in re)
{
string account = new System.Security.Principal.SecurityIdentifier(item.Value).Translate(typeof(System.Security.Principal.NTAccount)).ToString();
foreach (var group in PowerConfig.ServerSettings.Authorization.ForwardsList)
{
if (account == group)
{
ci2.AddClaim(new Claim(ClaimTypes.Role, "Forwards"));
}
}
foreach (var group in PowerConfig.ServerSettings.Authorization.ScheduledForwardsList)
{
if (account == group)
{
ci2.AddClaim(new Claim(ClaimTypes.Role, "ScheduledForwards"));
}
}
}
principal.AddIdentity(ci2);
return Task.FromResult(principal);
}
}
而不是
ci.AddClaim(...)
尝试principal.Identity.AddClaim(...)
.
ci
是按值分配的,因此您正在向 principal
的身份副本添加声明,因此当您返回 principal
时,它没有被更改。在第二个版本中,您正在修改ci2
,然后在返回之前将其添加到principal
,这就是它起作用的原因。
你也可以跳过
ci2
然后放
principal.AddIdentity(ci);
在同一个地方也应该有效。