【问题标题】:Security error when calling external web service in visual studio在 Visual Studio 中调用外部 Web 服务时出现安全错误
【发布时间】:2016-04-29 09:25:18
【问题描述】:

我正在尝试在 Visual Studio 中调用外部 Web 服务,但出现错误。

System.Security.SecurityException:请求“System.Security.Permissions.SecurityPermission,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089”类型的权限失败。 System.Security.SecurityException: 在 System.Security.CodeAccessSecurityEngine.Check(对象需求,StackCrawlMark& stackMark,布尔 isPermSet) 在 System.Security.CodeAccessPermission.Demand() 在 System.Net.ServicePointManager.set_ServerCertificateValidationCallback(RemoteCertificateValidationCallback 值)

以下是调用webservice的程序。

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read)]
    [return: SqlFacet(MaxSize = -1)]
    public static SqlString NYP_RestGet(SqlString uri)
    {
        String document;
        System.Net.ServicePointManager.ServerCertificateValidationCallback +=
        delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                                System.Security.Cryptography.X509Certificates.X509Chain chain,
                                System.Net.Security.SslPolicyErrors sslPolicyErrors)
        {
            return true; // **** Always accept
        };

        // Set up the request, including authentication
        WebRequest req = WebRequest.Create(Convert.ToString(uri));
        ((HttpWebRequest)req).UserAgent = "CLR web client on SQL Server";
        req.ContentType = "application/xml";
        ((HttpWebRequest)req).Accept = "application/xml";

        WebResponse resp = req.GetResponse();
        Stream dataStream = resp.GetResponseStream();
        StreamReader rdr = new StreamReader(dataStream);
        document = (String)rdr.ReadToEnd();


        rdr.Close();
        dataStream.Close();
        resp.Close();
         return (document);
    }
};

【问题讨论】:

    标签: web-services visual-studio-2012 sqlclr


    【解决方案1】:

    对于网络相关的请求,您需要将您的程序集设置为PERMISSION_SET = EXTERNAL_ACCESS。然而,不幸的是,使用System.Net.ServicePointManager.ServerCertificateValidationCallback 需要PERMISSION_SET = UNSAFE。如果您不明确需要覆盖 SSL 证书的处理,那么您应该删除该委托,因为将 Assembly 设置为 EXTERNAL_ACCESS 会更好。

    不幸的是,Visual Studio / SSDT (SQL Server Data Tools) 不能很容易地采取适当的步骤来允许您的程序集设置为EXTERNAL_ACCESSUNSAFE。但是,它们确实很容易将TRUSTWORTHY 选项设置为ON,这在很大程度上是个坏主意。

    除非绝对必要,否则请不要设置TRUSTWORTHY ON!只有在加载您未构建且无法重新签名的程序集时,它才应该是“必要的”。这主要发生在加载不受“支持”的 .NET Framework 库时,因此 SQL Server 的 CLR 主机中还没有。在这些情况之外,您不应该将数据库设置为 TRUSTWORTHY ON,因为它会打开一个安全漏洞。

    相反,最好执行以下操作:

    USE [master];
    
    CREATE ASYMMETRIC KEY [SomeKey]
      AUTHORIZATION [dbo]
      FROM EXECUTABLE FILE = 'C:\path\to\Some.dll';
    
    CREATE LOGIN [SomeLogin]
      FROM ASYMMETRIC KEY [SomeKey];
    
    GRANT EXTERNAL ACCESS ASSEMBLY TO [SomeLogin]; -- or "UNSAFE" instead of "EXTERNAL ACCESS"
    

    每个实例,每个键只需要执行一次上述操作。因此,如果您对所有程序集使用相同的snk / pfx 文件,那么上面显示的步骤只需为每个 SQL Server 实例执行一次;包含这些程序集的程序集和数据库的数量无关紧要。

    这种方法可以让您更好地保护数据库(通过将TRUSTWORTHY 设置为OFF)并允许更精细地控制哪些程序集甚至可以设置为EXTERNAL_ACCESS 和/或@987654340 @(因为您可以根据这些不同的密钥使用不同的密钥进行签名和登录)。

    有关安全选项的更详细演练,请参阅我在 SQL Server Central 上撰写的以下文章:Stairway to SQLCLR Level 4: Security (EXTERNAL and UNSAFE Assemblies)(需要免费注册)。


    其他说明:

    1. 有关通过 SQLCLR 调用 Web 服务和网页的更多注意事项,请在此处查看我的回答:Call web service from SQL CLR?
    2. 无需使用Convert.ToString(uri)。所有Sql* 类型都有一个.Value 属性,该属性返回适当的本机类型。所以用uri.Value替换它。
    3. SqlFunction 属性中不需要DataAccess = DataAccessKind.Read,因为您没有进行任何数据访问。设置 DataAccess = DataAccessKind.Read 会对性能造成轻微影响,因此,既然您没有使用它,请移除它。
    4. dataStreamrdr(分别是 StreamStreamReader)是“一次性”对象,所以你真的需要在它们上调用 .Dispose(),你可以这样做而不是 .Close()
    5. 您没有任何错误处理,这意味着如果在这两个对象上调用 Dispose 方法之前出现错误,您的进程可能会保持打开外部网络句柄,并且可能不会被释放直到应用程序域回收可能不会很长时间。您需要使用using 构造或正确构造try / catch / finally。如果不执行这两件事之一,在 SQL Server 中运行这是相当危险的代码。
    6. 有关使用 SQL Server 的 CLR 主机的各种细微差别的详细信息,请参阅我的文章:Stairway to SQLCLR Level 5: Development (Using .NET within SQL Server)(需要免费注册)。

    【讨论】:

      猜你喜欢
      • 2017-08-17
      • 2012-11-21
      • 1970-01-01
      • 2013-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多