如何将声明从 WS 联合身份验证回复转移到标识



我对.net core 2.1很陌生,我想如果我要构建/重建一个项目,我不妨使用新的东西。所以我一直在与 ASP.NET 核心身份作斗争 - 文档肯定还有一些不足之处。

我已经成功实施了身份验证 - 我重定向到我的 ADFS,然后再次返回,用户已登录。

然后我开始浏览授权。首先,我尝试了基于角色,但我读到角色没有多大用处,此外,我无法弄清楚为什么分配给用户的角色未能通过授权检查(ClaimsPrincipal.IsInRole 和剃须刀片页面的策略(。

我决定使用基于声明的授权,认为我可以使用通过 WS-Federation 提供的声明 - 我正在发送一些(名称、名称 ID、电子邮件地址、组(,其中组是作为字符串的组成员身份的非限定列表 - 但是,登录后我在 ClaimsPrincipal (HttpContext.User( 上看不到任何这些声明。

在登录期间中断流程,我可以看到对

_signInManager.GetExternalLoginInfoAsync()

肯定会从 ADFS 获得预期的索赔,但显然没有进入之后发生的任何事情。

就像我说的,我对它的内部工作原理很模糊,TBH 我真的不想太深入地了解我只需要知道我可以根据 ADFS 的组声明授权的细节。

我的项目或多或少是核心 2.1 网站的标准默认 asp.net 选择了个人帐户授权,然后我添加了对 WS 联合身份验证的修改,陪审团操纵了登录操作以直接重定向到 ADFS 而不是提示它。

如果您需要澄清,请告诉我,但它的要点是:

如何将组声明从 ADFS 获取到 ASP.NET 核心标识中,以便可以通过以下方式引用它们:

services.AddAuthorization(options =>
{
options.AddPolicy("RequireAdminGroup", policy =>
policy.RequireClaim("Group", "AD Admin Group Name")
);
});

另外,请随时指导我错过的任何答案。一整天都在阅读文档和搜索网络,今天根本没有真正的进展!

Identitiy 工作正常。您只是以错误的方式访问了声明。 在 Razor 页面中尝试以下操作。

@inject UserManager<ApplicationUser> UserManager
@{
var claims = await UserManager.GetClaimsAsync(await UserManager.GetUserAsync(User));
}

对于策略,您可以使用类 ClaimTypes in Startup.cs 来获取众所周知的声明 前任。:

policy.RequireClaim(ClaimTypes.WindowsAccountName));

为了添加额外的信息,这是我最终规避该问题的方式。ASP.NET 核心身份功能比我想要/需要的要重量级得多,而且文档有些缺乏。它还或多或少地劫持了来自联合源的声明,然后用自己的值替换它们。由于我只需要获取 ADFS 发送的组声明并在策略中使用它们,因此我做了如下操作:

删除对 ASP.NET 核心标识的所有引用。我不记得它们在我脑海中是什么,但它们应该很明显。

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
}

最后,您可以使用这些策略。就我而言,我使用的是剃刀页面,所以我只有一系列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>
}

显然,如果您要从页面隐藏链接/等,您还需要制定策略来防止该用户访问实际链接,因为没有什么可以阻止用户简单地尝试访问任何旧路径。

这就是我实现它的方式。如果有人有任何反馈告诉我我做了一些可怕的错误,我愿意接受:)

相关内容

  • 没有找到相关文章

最新更新