【问题标题】:How do I map a credential to a SQLCLR assembly in SQL Server?如何将凭据映射到 SQL Server 中的 SQLCLR 程序集?
【发布时间】:2020-05-02 09:20:51
【问题描述】:

我在 SQL Server 中有一个 CLR 程序集,我需要继承特定帐户的权限。 CLR 函数基本上只是抓取一个网页并以这种方式将其返回给 SQL:

    [SqlFunction]
    [return: SqlFacet(MaxSize = -1)]
    public static SqlChars Get(SqlChars H, SqlChars url)
    {
        var client = new WebClient();

        client.Credentials = CredentialCache.DefaultNetworkCredentials;

        AddHeader(H, client);
        return new SqlChars(
                client.DownloadString(
                    Uri.EscapeUriString(url.ToSqlString().Value)
                    ).ToCharArray());
    }

我希望它能够使用特定帐户详细信息通过 NTLM 进行身份验证。这在 SQL 之外的 C# 程序中运行良好,但作为 CLR 函数,它只返回 401 Unauthorized 消息,这是因为 DefaultNetworkCredentials 是 SQL Server 服务帐户的消息(我通过将服务设置为使用我的凭据来确认这一点,并且然后 CLR 完美运行)

我的理解是,这样做的方法是在 SQL Server 中使用该帐户的详细信息创建一个 Credential,因为这就是 documentation 所说的:

凭据提供了一种允许 SQL Server 身份验证用户在 SQL Server 之外拥有身份的方法。这主要用于在具有 EXTERNAL_ACCESS 权限集的程序集中执行代码。

我可以这样做,但我似乎无法找到任何方法将该凭据映射到程序集。我该怎么做?

【问题讨论】:

  • 我不确定该特定声明中的文档是否正确。这似乎没有出现在任何其他与凭据相关的页面上。无论哪种方式,凭据都映射到 SQL Server 登录,而不是程序集。而且,当您说“继承特定帐户的权限”时,您是指用于外部操作(如文件系统、网络、注册表等)的 Windows 帐户吗?您能否更新问题以准确说明您正在尝试执行的操作需要其他帐户的权限吗?谢谢。
  • @SolomonRutzky 更新解释 - 我希望它使用特定帐户详细信息进行一些 NTLM 身份验证。默认情况下,它会获取 SQL Server 服务帐户的详细信息
  • 嗨,丹。我已经用我的测试结果更新了我的答案。该文档似乎是错误的,实际上不能以这种方式使用凭据。但是,我确实注意到了两种选择。

标签: .net sql-server credentials impersonation sqlclr


【解决方案1】:

我不确定 SQL Server 中的凭据是否真的以这种方式工作(在那个文档页面中描述的方式)。但即使它们可以通过 SQLCLR 模块用于外部操作,也不会通过将任何东西分配给程序集。 SQL Server 中的凭据映射到 SQL Server 登录。因此,您可以将凭据映射到一个或多个 SQL Server 登录名,这些登录名将执行基于 SQLCLR 的模块。

而且,如果您需要外部操作来使用默认安全上下文(SQL Server 服务帐户)以外的安全上下文,那么您需要激活Impersonation within the .NET code。这样做将假定在 SQL Server 中执行基于 SQLCLR 的模块的 Windows 帐户的安全上下文。 SQL Server 登录不是 Windows 帐户,这就是它们通常无法在 .NET 代码中进行模拟的原因。 或许可以通过将 T-SQL 凭据映射到 SQL Server 登录名来实现(我已经对此进行了测试,但它不起作用;文档非常不正确;我将提交更正在 GitHub 上)。请记住WindowsIdentityWindowsImpersonationContext 对象是一次性的,因此您需要将它们包装在using(...){} 构造中,或者至少在finallyfinally 部分调用Dispose() 方法。 @ 或 try/finally 块。如果您使用的是 Windows Auth 登录,那么您可以进行此模拟,但它将模拟正在执行模块的任何登录,我假设它可以是不同的帐户(即并不总是您的),因此它们都需要访问外部资源。

另一种选择是通过new NetworkCredential() 直接在.NET 代码中提供凭据。这样做不仅适用于 SQL Server 登录,而且允许单个帐户进行连接(您当然可以从列表中查找凭据以根据某些条件使用不同的凭据,但这至少允许通过单个帐户访问远程资源)。

【讨论】:

  • 谢谢;这是一个非常全面的答案,我很欣赏测试工作。 Impersonation 可能确实有效,只有运行它的人才能访问该资源。我的目标是避免使用new NetworkCredential(),因为它意味着将凭据存储在某处,而这总是让我感到害怕。
  • @DanScally 不客气。而且我完全理解:不想存储密码,特别是如果它们需要以纯文本形式显示。可能还有其他方法可以创建凭据,但我没有时间研究。不过,如果需要访问的用户都拥有 Windows 登录并且这些登录可以访问远程资源,那么可以,使用模拟...祝你好运!
猜你喜欢
  • 2013-07-09
  • 2015-11-09
  • 2021-03-20
  • 2014-05-15
  • 1970-01-01
  • 2017-05-26
  • 2013-11-29
  • 1970-01-01
  • 2014-09-20
相关资源
最近更新 更多