【问题标题】:WCF Service invoked from SQL Server Stored Procedure through HTTPS通过 HTTPS 从 SQL Server 存储过程调用的 WCF 服务
【发布时间】:2018-05-14 07:35:11
【问题描述】:

我正在通过 HTTPS 服务从 SQL Server 存储过程调用一个 WCF 服务并出现以下错误:

证书颁发机构无效或不正确。

通过 HTTP 调用服务时服务调用成功,但通过 HTTPS 调用服务时出现问题。

当我通过 SOAP UI 调用它时,通过 HTTPS 的相同 WCF 服务调用是成功的。但是,当从 SQL Server 存储过程调用服务时,问题会通过 HTTPS 出现。

【问题讨论】:

  • sql server 是本地的还是托管在其他服务器上?
  • 您好 Popo,SQL Server 托管在另一台服务器上。但我已经在安装了 SQL Server 的那台机器上安装了客户端证书。
  • 我现在开始工作了。请参阅下面的答案。

标签: sql-server wcf https


【解决方案1】:

谢谢大家,我搞定了。实际上证书名称需要在下面的存储过程中明确指定,这在我的实现中是缺失的。

EXEC @hResult = sp_OAMethod
           @objectID,
           'setOption',
           NULL,
           3,
           'LOCAL_MACHINE\My\'Certificate Name';

以下是从存储过程调用 Web 服务的完整存储过程实现。

CREATE PROCEDURE [dbo].[Usp_INT_SendHttpRequest]
    @URI          VARCHAR(2000) = '',
    @methodName   VARCHAR(50)   = '',
    @requestBody  VARCHAR(8000) = '',
    @SoapAction   VARCHAR(255),
    @UserName     NVARCHAR(100), -- Domain\UserName or UserName 
    @Password     NVARCHAR(100),
    @responseText VARCHAR(8000) OUTPUT
AS
    BEGIN
       SET NOCOUNT ON;
       IF @methodName = ''
          BEGIN
             SELECT FailPoint = 'Method Name must be set';
             RETURN;
          END;
       SET @responseText = 'FAILED';
       DECLARE @objectID INT;
       DECLARE @hResult INT;
       DECLARE @source VARCHAR(255), @desc VARCHAR(255);
       EXEC @hResult = sp_OACreate
           'MSXML2.ServerXMLHTTP',
           @objectID OUT;
       IF @hResult <> 0
          BEGIN
             EXEC sp_OAGetErrorInfo
                 @objectID,
                 @source OUT,
                 @desc OUT;
             SELECT hResult = CONVERT(VARBINARY(4), @hResult),
                   source = @source,
                   description = @desc,
                   FailPoint = 'Create failed',
                   MedthodName = @methodName;
             GOTO destroy;
             RETURN;
          END;
       EXEC @hResult = sp_OAMethod
           @objectID,
           'setOption',
           NULL,
           3,
           'LOCAL_MACHINE\My\ClientSignedByDevCA';
       IF @hResult <> 0
          BEGIN
             EXEC sp_OAGetErrorInfo
                 @objectID,
                 @source OUT,
                 @desc OUT;
             SELECT hResult = CONVERT(VARBINARY(4), @hResult),
                   source = @source,
                   description = @desc,
                   FailPoint = 'Set Certificate failed',
                   MedthodName = @methodName;
             GOTO destroy;
             RETURN;
          END;

-- open the destination URI with Specified method 
       EXEC @hResult = sp_OAMethod
           @objectID,
           'open',
           NULL,
           @methodName,
           @URI,
           'false',
           @UserName,
           @Password;
       IF @hResult <> 0
          BEGIN
             EXEC sp_OAGetErrorInfo
                 @objectID,
                 @source OUT,
                 @desc OUT;
             SELECT hResult = CONVERT(VARBINARY(4), @hResult),
                   source = @source,
                   description = @desc,
                   FailPoint = 'Open failed',
                   MedthodName = @methodName;
             GOTO destroy;
             RETURN;
          END;
-- set request headers 
       EXEC @hResult = sp_OAMethod
           @objectID,
           'setRequestHeader',
           NULL,
           'Content-Type',
           'text/xml;charset=UTF-8';
       IF @hResult <> 0
          BEGIN
             EXEC sp_OAGetErrorInfo
                 @objectID,
                 @source OUT,
                 @desc OUT;
             SELECT hResult = CONVERT(VARBINARY(4), @hResult),
                   source = @source,
                   description = @desc,
                   FailPoint = 'SetRequestHeader failed',
                   MedthodName = @methodName;
             GOTO destroy;
             RETURN;
          END;
-- set soap action 
       EXEC @hResult = sp_OAMethod
           @objectID,
           'setRequestHeader',
           NULL,
           'SOAPAction',
           @SoapAction;
       IF @hResult <> 0
          BEGIN
             EXEC sp_OAGetErrorInfo
                 @objectID,
                 @source OUT,
                 @desc OUT;
             SELECT hResult = CONVERT(VARBINARY(4), @hResult),
                   source = @source,
                   description = @desc,
                   FailPoint = 'SetRequestHeader failed',
                   MedthodName = @methodName;
             GOTO destroy;
             RETURN;
          END;
       DECLARE @len INT;
       SET @len = LEN(@requestBody);
       EXEC @hResult = sp_OAMethod
           @objectID,
           'setRequestHeader',
           NULL,
           'Content-Length',
           @len;
       IF @hResult <> 0
          BEGIN
             EXEC sp_OAGetErrorInfo
                 @objectID,
                 @source OUT,
                 @desc OUT;
             SELECT hResult = CONVERT(VARBINARY(4), @hResult),
                   source = @source,
                   description = @desc,
                   FailPoint = 'SetRequestHeader failed',
                   MedthodName = @methodName;
             GOTO destroy;
             RETURN;
          END;
       EXEC @hResult = sp_OAMethod
           @objectID,
           'send',
           NULL,
           @requestBody;
       IF @hResult <> 0
          BEGIN
             EXEC sp_OAGetErrorInfo
                 @objectID,
                 @source OUT,
                 @desc OUT;
             SELECT hResult = CONVERT(VARBINARY(4), @hResult),
                   source = @source,
                   description = @desc,
                   FailPoint = 'Send failed',
                   MedthodName = @methodName;
             GOTO destroy;
             RETURN;
          END;
       DECLARE @statusText VARCHAR(1000), @status VARCHAR(1000); 
-- Get status text 
       EXEC sp_OAGetProperty
           @objectID,
           'StatusText',
           @statusText OUT;
       EXEC sp_OAGetProperty
           @objectID,
           'Status',
           @status OUT;
       SELECT @status,
            @statusText,
            @methodName; 
-- Get response text 
       EXEC sp_OAGetProperty
           @objectID,
           'responseText',
           @responseText OUT;
       IF @hResult <> 0
          BEGIN
             EXEC sp_OAGetErrorInfo
                 @objectID,
                 @source OUT,
                 @desc OUT;
             SELECT hResult = CONVERT(VARBINARY(4), @hResult),
                   source = @source,
                   description = @desc,
                   FailPoint = 'ResponseText failed',
                   MedthodName = @methodName;
             GOTO destroy;
             RETURN;
          END;
       destroy:
       EXEC sp_OADestroy
           @objectID;
       SET @responseText = 'SUCCESS'
       SET NOCOUNT OFF;
    END;

【讨论】:

  • 选项 3 被命名为 SXH_OPTION_SELECT_CLIENT_SSL_CERT。当证书不在本地机器存储中,或者有多个证书时,应该使用它。 +1 用于详细的存储过程。您能否检查证书是否在“本地机器”中而不是(可能)在“个人”商店中?
  • 我必须使用它,即使证书在我本地机器的个人存储中。可能是因为,个人存储中有多个证书。
【解决方案2】:

在我看来,错误与“证书颁发机构”有关,即服务器证书的颁发者。可能您使用自签名证书。在这种情况下,您还需要在客户端计算机上的“受信任的根证书颁发机构”中安装 CA 证书。否则客户端将无法准确验证服务器证书,因为它无法验证其颁发者(证书颁发机构)。

【讨论】:

  • 那么,你已经在SQL Server的主机上安装了CA证书(除了服务器证书)?
  • 是的,即使在那之后它也没有用。实际上我并没有在存储过程实现中明确指定证书名称。
【解决方案3】:

也许您需要向运行 WCF 的帐户授予对包含私钥的文件的读取权限。这里有分步说​​明https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-make-x-509-certificates-accessible-to-wcf

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    • 2013-08-31
    • 1970-01-01
    • 2012-02-10
    • 1970-01-01
    • 2014-03-30
    相关资源
    最近更新 更多