首页 > 解决方案 > 如何将凭据映射到 SQL Server 中的 SQLCLR 程序集?

问题描述

我在 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完美地工作)

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

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

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

标签: .netsql-servercredentialsimpersonationsqlclr

解决方案


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

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

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


推荐阅读