我正在使用 ADFS Server 2016 被动重定向对 asp.net mvc 网站的用户进行身份验证,但我无法从 SQL 属性存储中获取声明。我有兴趣发现我做错了什么或遗漏了什么。
旁注:我使用的是 Framework 4.5 中的 System.Identity 库(我没有引用为旧框架版本创建的 Microsoft.Identity 库;我偶然发现的大多数 ADFS 代码示例都使用这些旧库)。
基础工作良好。所有这些都在一个域中。我将我的 asp.net web.config 设置为将用户重定向到我的 ADFS 服务器进行身份验证。ADFS 服务器成功地对用户进行身份验证并将用户重定向回我的 asp.net 网站。在 ADFS 上,我有一个声明颁发策略规则,我只需将所有声明从 Active Directory 传回。
在网站上,我可以遍历用户的 Claims 集合并显示它们。这是我在声明中迭代的 *.cshtml 页面中的代码,它工作正常:
@using System.Security.Claims;
@{
var currentPrincipalIdentity = (ClaimsIdentity)System.Threading.Thread.CurrentPrincipal.Identity;
}
@foreach (Claim claim in currentPrincipalIdentity.Claims)
{
<br/>@claim.Type : @claim.Value
}
除了来自 Active Directory 的这些声明之外,我还想从 SQL Server 数据库中获取一堆角色并将它们作为角色添加到声明集合中。我正在从旧的 asp.net Membership 数据库中获取角色。作为第 1 步,我只想在 SQL 语句中硬编码用户名(最终我需要弄清楚如何将用户名作为参数传递给 SQL 语句,但这将是第 2 步)。
首先,我提供了 ADFS 服务器在我的 SQL Server 上以读/写/执行权限运行的身份(当我取消这些权限时,我得到一个权限错误,这让我确信我的 SQL 语句正在执行)。
在我的 AD FS 中,我通过右键单击“属性存储”节点添加了一个 SQL Server 属性存储,选择“SQL”的属性存储类型,命名为“SQLServer”,并添加了一个连接字符串,如下所示:
Server=SqlDev01; Database=MyLegacyMembershipDatabase; Integrated Security=SSPI;
然后我选择“Relying Party Trusts”文件夹,选择我感兴趣的信任,然后选择“Edit Claim Issuance Policies”。我有一个有效的规则;它只是传回所有 Active Directory 声明。我可以在我的网页上看到所有这些声明(upn、名称、windowsaccountname、我所有的组 sid 等):
c:[]
=> issue(claim = c);
我正在尝试添加第二条自定义规则来读取旧会员数据库。在我的 ADFS 中,我单击“添加规则”、“使用自定义规则发送声明”,并将其添加为规则:
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"]
=> add(store = "SQLServer", types =
("http://schemas.microsoft.com/ws/2008/06/identity/claims/role"), query =
"select r.RoleName AS Role from dbo.aspnet_Roles r INNER JOIN
dbo.aspnet_UsersInRoles uir ON r.RoleId = uir.RoleId INNER JOIN
dbo.aspnet_Users u ON uir.UserId = u.UserId WHERE u.UserName = '[hard-coded
value here]' OR u.UserName={0}", param = c.Value);
它保存得很好,但是当我重新运行页面时没有任何变化;我仍然得到 Active Directory 声明的原始集合,但没有来自 SQL Server 的数据。
我确信 SQL Server 语句正在执行,因为如果我从 SQL Server 中删除运行 ADFS 的身份的权限,我会收到错误消息,如果我故意弄乱 SQL 语法,我会收到错误消息。如果我扭转这些故意的错误,那么页面会再次正常运行。但我从未在 Claims 集合中看到我想看到的角色。
根据我对自定义规则的理解,“ http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn ”作为参数传递到查询中,这就是我上面有 OR 语句的原因;我的最终目标是将用户的 UPN 作为参数传递给 SQL 查询。
我错过了什么或做错了什么?额外的问题——假设我能正常工作,你能告诉我如何将用户的 UPN 作为参数传递给 SQL 查询吗?