【问题标题】:How to make a WCF Service work with https?如何使 WCF 服务与 https 一起工作?
【发布时间】:2014-11-05 15:46:47
【问题描述】:

我正在尝试在我的 WCF 服务中启用 https。我已将 SSL 证书添加到我的本地主机,当我在浏览器中使用 https 时,我能够查看 WSDL。并且 WCF 服务在 web.config 中没有 SSL 配置的情况下可以正常工作。但是,一旦我将其更改为使用 https,就会出现以下错误。如果有人可以为我指出此问题的解决方案,这将很有帮助,因为此错误没有太多参考。

at Microsoft.Http.HttpStageProcessingAsyncResult.Complete(HttpStage stage, Exception e)
at Microsoft.Http.HttpStageProcessingAsyncResult.NextRequest(HttpStageProcessingAsyncResult self)
at Microsoft.Http.HttpStageProcessingAsyncResult..ctor(HttpStageProcessingAsyncState state, AsyncCallback callback, Object user)
at Microsoft.Http.HttpClient.Send(HttpRequestMessage request)
at Microsoft.Http.HttpClient.Send(HttpMethod method, Uri uri, RequestHeaders headers, HttpContent content)
at Microsoft.Http.HttpClient.Send(HttpMethod method, Uri uri)
at Microsoft.Http.HttpMethodExtensions.Method(HttpClient client, HttpMethod method, Uri uri)
at Microsoft.Http.HttpMethodExtensions.Method(HttpClient client, HttpMethod method, String uri)
at Microsoft.Http.HttpMethodExtensions.Get(HttpClient client, String uri)
at MobileScreening.Client.CommonTests.LoginPost(HttpClient client, String username, String password) in c:\TFS Projects\MobileScreening\MobileScreening.Client\CommonTests.cs:line 118

我向服务发出请求的客户端代码

static string LoginPost(HttpClient client, string username, string password)
    {
        string key = string.Empty;

        try
        {
            var user = new UserCredentials
            {
                Email = username,
                Password = password
            };

            Console.WriteLine("User Authentication:");

            HttpContent content = HttpContentExtensions.CreateJsonDataContract(user);

            using (HttpResponseMessage response = client.Post("AuthenticationService.svc/", content))
            {
                Console.WriteLine(response.Content.ReadAsString());
                Console.WriteLine(response.Headers.ToString());

                key = response.Headers["MobileScreening"] ?? string.Empty;
            }
        }
        catch (Exception ex)
        {
            var stack = ex.StackTrace;
            var innerException = ex.InnerException;
            var message = ex.Message;
        }

        return key;
    }

我与操作合约的界面

public interface IAuthenticationService
{
    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    AuthenticationWrapper Authenticate(UserCredentials user);
}

我的服务来验证用户:

public class AuthenticationService : IAuthenticationService
{
    public AuthenticationWrapper Authenticate(UserCredentials user)
    {
        string email = user.Email ?? string.Empty;
        string password = user.Password ?? string.Empty;

        var authentication = new Authentication();

        var authenticationWrapper = new AuthenticationWrapper();

        if (!authentication.AuthenticateUser(email, password))
        {
            const string description = "Authentication failed. Username and/or password is incorrect.";

            BLL.Authentication.ThrowAuthorisationFailed(description, email);

            WebOperationContext ctx = WebOperationContext.Current;
            ctx.OutgoingResponse.StatusCode = HttpStatusCode.Unauthorized;

            authenticationWrapper.Code = (short)HttpStatusCode.Unauthorized;
            authenticationWrapper.Status = HttpStatusCode.Unauthorized.ToString();
            authenticationWrapper.Message = description;
            return authenticationWrapper;
        }
        else
        {
            const string description = "Authentication: Authenticate User";

            LogHandler.LogMessage(email, description, Common.Event.LoginSuccessful);

            string authorisationKey = authentication.CreateAuthorisationKey(email);

            WebOperationContext ctx = WebOperationContext.Current;
            ctx.OutgoingResponse.Headers.Add(Common.AuthorisationHeader, authorisationKey);
            ctx.OutgoingResponse.StatusCode = HttpStatusCode.OK;

            authenticationWrapper.Code = (short)HttpStatusCode.OK;
            authenticationWrapper.Status = HttpStatusCode.OK.ToString();
            authenticationWrapper.Message = description;
            return authenticationWrapper;
        }
    }
}

最后是我的 web.config 服务配置

<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
  multipleSiteBindingsEnabled="true" />
<services>
  <service name="MobileScreening.ServiceApp.AuthenticationService">
    <endpoint address="AuthenticationService" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="MobileScreening.ServiceApp.IAuthenticationService" />
    <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
  </service>
  <service name="MobileScreening.ServiceApp.ProgrammeService">
    <endpoint address="ProgrammeService" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="MobileScreening.ServiceApp.IProgrammeService" />
    <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
  </service>
  <service name="MobileScreening.ServiceApp.ActivityService">
    <endpoint address="ActivityService" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="MobileScreening.ServiceApp.IActivityService" />
    <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
  </service>
  <service name="MobileScreening.ServiceApp.UserConfigurationService">
    <endpoint address="UserConfigurationService" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="MobileScreening.ServiceApp.IUserConfigurationService" />
    <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
  </service>
</services>
<bindings>
  <basicHttpBinding>
    <binding name="secureHttpBinding">
      <security mode="Transport">
        <transport clientCredentialType="Basic"/>
      </security>
    </binding>
  </basicHttpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior>
      <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
      <serviceMetadata httpsGetEnabled="true"/>
      <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
      <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
</system.serviceModel>

【问题讨论】:

  • 谁签署了证书?您是从哪台机器调用服务?
  • 这是我使用 IIS 创建的自签名证书,我在本地机器上使用它进行测试。我从同一台机器调用服务。
  • 在查看 WSDL 之前浏览器是否给您任何警告?
  • 我在 FireFox 上没有得到任何东西,但 IE 显示“此网站提供的安全证书是为不同网站的地址颁发的。”。我认为这是因为我使用的是颁发给我的机器名称的证书。所以我创建了一个使用 SelfSSL.exe 将其发布到我的本地主机并将该证书分配给服务应用程序的证书。但我在 IE 上收到相同的错误消息。
  • 您发布了客户端堆栈跟踪,但没有返回实际的错误消息......

标签: c# web-services wcf ssl https


【解决方案1】:

使用您的机器名称而不是本地主机创建新的自签名证书。配置您的解决方案以使用新证书,并确保它安装在受信任的根证书颁发机构下的客户端计算机中(在您的情况下,客户端也是服务器)。

另外,您也可以尝试创建指向机器的完全限定域名的证书。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    • 2020-10-24
    • 1970-01-01
    相关资源
    最近更新 更多