我对.net core 2.1还是很陌生,我想如果我要构建/重建一个项目,我不妨使用新事物。因此,我一直在与ASP.NET Core身份作斗争一段时间-该文档肯定还有一些不足之处。
我已成功实现身份验证-我重定向到我的ADFS,然后再次返回,并且用户已登录。
然后我开始查看授权。首先,我尝试了基于角色的方法,但是我已经知道角色使用不多,而且我无法弄清楚为什么分配给用户的角色未通过授权检查(ClaimsPrincipal.IsInRole和剃刀页面的策略)。
我决定使用基于声明的授权,确定我可以使用通过WS-Federation提供的声明-我要发送一些信息(名称,名称ID,电子邮件地址,组),其中组是不合格列表的组成员身份作为字符串-但是,登录后我在ClaimsPrincipal(HttpContext.User)上看不到任何这些声明。
在登录过程中中断流程,我可以看到对
的调用_signInManager.GetExternalLoginInfoAsync()
肯定已经从ADFS获得了预期的要求,但是显然没有考虑到之后发生的一切。
就像我说过的那样,我对它的内部工作方式和TBH都非常模糊,我真的不想深入了解具体问题,我只需要知道我可以根据ADFS的团体声明进行授权。 / p>
我的项目或多或少是标准的默认asp.net core 2.1网站,并选择了个人帐户授权,然后我添加了WS-Federation的修改,并评审了Login操作以直接重定向到ADFS比提示它。
如果需要澄清,请告诉我,但是要点是:
如何将来自ADFS的组声明放入ASP.NET Core身份,因此我可以通过以下方式引用它们:
services.AddAuthorization(options =>
{
options.AddPolicy("RequireAdminGroup", policy =>
policy.RequireClaim("Group", "AD Admin Group Name")
);
});
此外,请随时指导我错过的任何答案。整天都在阅读文档并在网络上搜索,而今天却没有任何进展!
答案 0 :(得分:1)
身份正常运行。您刚刚以错误的方式访问了声明。 在Razor页面中尝试以下操作。
@inject UserManager<ApplicationUser> UserManager
@{
var claims = await UserManager.GetClaimsAsync(await UserManager.GetUserAsync(User));
}
对于策略,可以在Startup.cs中使用类ClaimTypes来获取众所周知的Claims 例如:
policy.RequireClaim(ClaimTypes.WindowsAccountName));
答案 1 :(得分:0)
要添加更多信息,以下是我最终规避此问题的方法。 ASP.NET Core Identity功能比我想要的/需要的要重得多,并且缺少文档。它还或多或少地从联邦来源劫持了索赔,然后用其自己的值替换了它们。因为我只需要获取ADFS发送的团体声明并将其用于策略中,所以我做了类似的事情:
删除对ASP.NET Core Identity的所有引用。我不记得他们在我头顶上掉了什么,但是找到它们应该很明显。
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
})
.AddWsFederation(options =>
{
options.MetadataAddress = "https://federationservicesurl/";
options.Wtrealm = "realmname";
options.SignOutWreply = "https://signoutaddress if you want it";
})
.AddCookie(options =>
{
options.AccessDeniedPath = "/AccessDenied"; // If you need one
options.ExpireTimeSpan = TimeSpan.FromMinutes(20); // Or from config
});
这将添加身份验证选项,ws联邦中间件和cookie,以使其起作用。然后添加授权:
services.AddAuthorization(options =>
{
// Any Admins
options.AddPolicy("RequireGroup", policy =>
policy.RequireClaim("http://schemas.xmlsoap.org/claims/Group", "Group 1", "Group 2")
);
//... more policies
}
最后,您可以使用这些策略。就我而言,我使用的是Razor Pages,所以我只有AuthorizeFolder/AuthorizePage
范围。
services.AddRazorPagesOptions(options =>
{
options.Conventions.AllowAnonymousToPage("/AccessDenied");
options.Conventions.AllowAnonymousToPage("/SignedOut");
options.Conventions.AllowAnonymousToPage("/SignOut");
options.Conventions.AuthorizeFolder("/Network", "RequireGroup");
options.Conventions.AuthorizePage("/About", "RequireGroup");
// ... more directives
})
那行得通。如果您还想隐藏界面片段,则可以这样做。同样,我使用的是Razor而不是纯MVC,所以我不确定如何以MVC方式实现此功能,但是我在顶部的cshtml文件中执行了此操作:
@inject IAuthorizationService AuthorizationService
@{
var requiregroup= (await AuthorizationService.AuthorizeAsync(User, "RequireGroup"));
}
然后:
@if (requiregroup.Succeeded)
{
<div>some content that requires the policy RequireGroup</div>
}
很显然,如果您要隐藏页面中的链接/等,则还需要制定一些策略,以防止该用户访问实际链接,因为没有什么可以阻止用户简单地尝试访问任何旧路径。
这就是我实现它的方式。如果有人有任何反馈要告诉我我做错了非常严重的事,我可以接受:)