Web services 在visual studio中调用外部web服务时出现安全错误

Web services 在visual studio中调用外部web服务时出现安全错误,web-services,visual-studio-2012,sqlclr,Web Services,Visual Studio 2012,Sqlclr,我试图在VisualStudio中调用外部Web服务,但遇到了错误 System.Security.SecurityException:请求类型为“System.Security.Permissions.SecurityPermission,mscorlib,版本=4.0.0.0,区域性=neutral,PublicKeyToken=b77a5c561934e089”的权限失败。 System.Security.SecurityException: 在System.Security.CodeAc

我试图在VisualStudio中调用外部Web服务,但遇到了错误

System.Security.SecurityException:请求类型为“System.Security.Permissions.SecurityPermission,mscorlib,版本=4.0.0.0,区域性=neutral,PublicKeyToken=b77a5c561934e089”的权限失败。 System.Security.SecurityException: 在System.Security.CodeAccessSecurityEngine.Check(对象请求、堆栈爬网标记和堆栈标记、布尔isPermSet) 在System.Security.CodeAccessPermission.Demand()中 位于System.Net.ServicePointManager.set_服务器CertificateValidationCallback(RemoteCertificateValidationCallback值)

下面是调用Web服务的程序

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);
    }
};

对于网络相关请求本身,您需要将程序集设置为
PERMISSION\u set=EXTERNAL\u ACCESS
。但是,使用
System.Net.ServicePointManager.ServerCertificateValidationCallback
不幸地需要
权限设置=不安全
。如果您不明确需要覆盖SSL证书的处理,那么您应该删除该委托,因为将程序集设置为
EXTERNAL\u ACCESS
会更好

不幸的是,VisualStudio/SSDT(SQL Server数据工具)并不能使您轻松地采取所需的适当步骤,以便将程序集设置为
外部访问
不安全
。但是,它们确实可以很容易地将
可信
选项设置为
打开
,这通常是个坏主意

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

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

使用[master];
创建非对称密钥[SomeKey]
授权[dbo]
从可执行文件='C:\path\to\Some.dll';
创建登录名[SomeLogin]
来自非对称密钥[某个密钥];
授予[SomeLogin]对程序集的外部访问权限;--或“不安全”而不是“外部访问”
每个实例、每个键只需执行一次上述操作。因此,如果对所有程序集使用相同的
snk
/
pfx
文件,则每个SQL Server实例只需执行一次上述步骤;包含这些程序集的程序集和数据库的数量无关紧要

这种方法允许您在数据库上保持更好的安全性(通过将
trustable
设置为
OFF
),并允许更精细地控制哪些程序集甚至允许设置为
外部\u访问
和/或
不安全
(因为您可以根据不同的密钥使用不同的密钥进行签名和登录)

有关安全选项的详细介绍,请参阅我在SQLServerCentral上写的以下文章:(需要免费注册)


其他说明:

  • 有关通过SQLCLR调用Web服务和网页的更多说明,请参见我的回答:
  • 无需使用
    Convert.ToString(uri)
    。所有
    Sql*
    类型都有一个
    .Value
    属性,该属性返回适当的本机类型。因此,请将其替换为
    uri.Value
  • 您不需要
    DataAccess=DataAccessKind.Read
    SqlFunction
    属性中,因为您没有进行任何数据访问。设置
    DataAccess=DataAccessKind.Read
    对性能有轻微影响,因此,由于您没有使用它,只需将其删除即可
  • dataStream
    rdr
    (分别是
    Stream
    StreamReader
    )都是“一次性”对象,因此您确实需要对它们调用
    .Dispose()
    ,而不是
    .Close()
  • 您没有任何错误处理,这意味着如果在对这两个对象调用
    Dispose
    方法之前发生错误,您的进程可能会保持打开外部网络句柄,并且在应用程序域回收之前,该句柄可能不会释放,这可能不会持续很长时间。您需要使用
    using
    构造或正确构造一个
    尝试
    /
    捕获
    /
    最后
    。在SQL Server中运行而不执行这两项操作之一,这是相当危险的代码
  • 有关使用SQLServer的CLR主机的各种细微差别的更多详细信息,请参阅我的文章:(需要免费注册)

  • 对于网络相关请求本身,您需要将程序集设置为
    PERMISSION\u set=EXTERNAL\u ACCESS
    。但是,使用
    System.Net.ServicePointManager.ServerCertificateValidationCallback
    不幸的是,需要
    PERMISSION\u set=UNSAFE
    。如果您不明确需要覆盖SSL的处理证书,那么您应该去掉该委托,因为将程序集设置为
    EXTERNAL\u ACCESS
    会更好

    不幸的是,Visual Studio/SSDT(SQL Server数据工具)不便于采取所需的适当步骤将程序集设置为
    外部访问
    不安全
    。但是,它们可以轻松地将
    可信
    选项设置为
    打开
    ,这通常是一个坏主意

    除非绝对必要,否则请不要在上设置
    Trustly!并且只有在加载未生成且无法重新签名的程序集时才应设置为“必需”。这通常发生在加载.NE时