如何使用 WindowsIdentity 和 SQL Server 集成安全设置表单身份验证

Posted

技术标签:

【中文标题】如何使用 WindowsIdentity 和 SQL Server 集成安全设置表单身份验证【英文标题】:How to setup Forms Authentication with WindowsIdentity and SQL Server Integrated Security 【发布时间】:2009-09-24 19:14:22 【问题描述】:

这是我们当前的设置。我们配置了 Active Directory(域名为 mis1)来处理我们所有的身份验证问题。我们为 impersonation=true 设置了 Web 应用程序,以便我们可以在用户登录时调用数据库查询。对于这个特定的应用程序,IIS 设置为匿名访问,我们可以进行表单身份验证。

为了我们的数据库安全,我们在数据库服务器上设置了本地组,并根据应用程序的需要将用户添加到这些组中。例如,对于同一个 FancyPants 应用程序,我们将有一个“FancyPantsManager”组和一个“FancyPantsUser”组。然后我们设置 SQL Server 2005 登录以映射到服务器上的这些本地组。

我想做的是为用户提供一个登录页面,该页面通过 AD 进行身份验证,然后如果成功,则转到数据库服务器以获取他们的角色(通​​过调用 xp_logininfo)以存储在用户的会话中。

到目前为止,我通过对 avapi32.dll 文件中的 LogonUser 方法执行 p/Invoke 成功地验证了 Active Directory 的表单身份验证。然后,我获取生成的令牌并生成一个 WindowsIdentity 对象并模拟用户。代码如下所示:

Private Sub loginMain_Authenticate _
               (ByVal sender As Object, _
                ByVal e As System.Web.UI.WebControls.AuthenticateEventArgs) _
        Handles loginMain2.Authenticate

   ' Assume variables properly declared

   IsAuthenticated = LogonUser(UserName, LOGON_DOMAIN, UserPass, 
                               LOGON_TYPE, LOGON_PROVIDER, ResultToken)

   If IsAuthenticated

      ' Setup impersonation for validated user.
      WindowsId = New WindowsIdentity(ResultToken)
      IdentContext = WindowsId.Impersonate()

      ' Call stored procedure to retrieve roles using validated user for login.
      GetUserRoles(UserName)

   End If

End Sub

当我单步调试调试器并输入正确的 ID 和密码时。我通过了身份验证,查看生成的 WindowsIdentity 对象,它指出我的 ID 是“mis1\c07884”,这正是模拟访问 SQL Server 所需要的。但是,当调用 GetRoles 方法时,我收到以下错误消息:

System.Data.SqlClient.SqlException: Could not obtain information 
about Windows NT group/user 'c07884', error code 0xffff0002.

在我看来,模拟过程中出现了一些错误。我错过了什么?

【问题讨论】:

【参考方案1】:

关注这个问题可能会有所帮助? Active Directory: Retrieving User Information

【讨论】:

不!...我想这不是你想要的,是吗? 关闭,但我需要一个授权令牌,以便我可以连接到数据库,以及为用户的 Web 会话保存部分票证。【参考方案2】:

已编辑以删除不相关的内容。

xp_logininfo。看起来您调用它时将帐户名作为不带域的用户名传递给它。这实际上解释了为什么错误消息说c07884 not found 而不是mis1\c07884 not found。错误 0xFFFF002 可能是错误 2 ERROR_FILE_NOT_FOUND

目前最快的解决方法可能是传递正确的帐户名称:

GetUserRoles(string.Format("0\\1"), LOGON_DOMAIN, UserName));

您应该考虑重写过程以通过不带参数调用x_logininfo 来检索模拟 用户信息以返回当前用户的信息。更好的是,只需 SELECT * FROM sys.login_token

如果您在 ASP 中只需要组成员身份,那么您已经在 WindowsIdentity.Groups 中拥有它。

【讨论】:

我在使用 WindowsIdentity.Groups 时遇到的问题是这些组是数据库服务器的本地组,而不是整个域名。群组是否能够从单个服务器而不是整个域中提取成员资格? 当我调用 GetUserRoles 时,连接字符串被配置为使用 SSPI,我假设这意味着它将采用登录的 WindowsIdentity 的模拟凭据,由于某种原因返回为 c07884 而没有域,有没有办法更新与登录关联的“名称”? 数据库主机是否加入了mis1域(或者它是否加入了信任mis1的域)? 好问题。我现在不确定。我想说是的,但需要与我们的运维人员谈谈。

以上是关于如何使用 WindowsIdentity 和 SQL Server 集成安全设置表单身份验证的主要内容,如果未能解决你的问题,请参考以下文章

WindowsIdentity winId = (WindowsIdentity)HttpContext.Current.User.Identity;如何使这个演员工作;目前它失败了

C# - 获取 ASPNET WindowsIdentity

如何将 WindowsIdentity 转换为 NetworkCredential?

如何使用 IIS 从 Blazor 服务器获取 WindowsIdentity.RunImpersonated(token, action) 的 HttpContext(或 AccessToken)

WindowsIdentity.Impersonate 和 PostBack 问题

WindowsIdentity.GetCurrent().Impersonate() 做啥