【问题标题】:MessageSecurityException: Security processor was unable to find a security header in the messageMessageSecurityException:安全处理器无法在消息中找到安全标头
【发布时间】:2012-05-08 14:16:54
【问题描述】:

Mono for Android 的安全 WCF 服务的状态如何?到 SOAP 1.2 了吗? 我正在为一个将与 WCF 服务交互的 Android 应用程序编写 POC,但我正在努力让事情正常工作。

我正在尝试连接到具有TransportWithMessageCredential 安全性的服务。但是我在服务器端遇到错误。

这是服务器端错误:

MessageSecurityException:安全处理器无法找到 消息中的安全标头。这可能是因为消息是 一个不安全的故障或因为有一个绑定不匹配之间 沟通方。如果服务配置为 安全性和客户端没有使用安全性。

服务器配置:

<service name="BrandDirector.ApplicationServer.Core.Services.UI.Products.Specifications.IngredientService" 
         behaviorConfiguration="CredentialValidation">
    <endpoint address="/BasicHttp"
        binding="basicHttpBinding"
        bindingConfiguration="BDBasicHttpBindingWithSecurity" 
        contract="BrandDirector.ApplicationServer.Core.Services.UI.Products.Specifications.IIngredientService" />
    <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>

<behavior name="CredentialValidation">
  <serviceMetadata httpGetEnabled="true" />
  <serviceDebug includeExceptionDetailInFaults="true" />
  <HttpStatusCode200Behavior />
  <serviceCredentials type="BrandDirector.ApplicationServer.Core.Security.Authentication.PasswordServiceCredentials, BrandDirector.ApplicationServer.Core.Security, Version=1.0.0.0, Culture=neutral">
    <userNameAuthentication userNamePasswordValidationMode="Custom"
      customUserNamePasswordValidatorType="BrandDirector.ApplicationServer.Core.Security.CredentialValidator, BrandDirector.ApplicationServer.Core.Security" />
  </serviceCredentials>
</behavior>

<extensions>
  <behaviorExtensions>
    <add name="HttpStatusCode200Behavior" type="BrandDirector.ApplicationServer.Core.Services.Common.ServiceModel.HttpStatusCode200BehaviorExtension, BrandDirector.ApplicationServer.Core.Services.Common" />
  </behaviorExtensions>

  <basicHttpBinding>
    <binding name="BDBasicHttpBindingWithSecurity" messageEncoding="Text" maxReceivedMessageSize="655536">
      <security mode="TransportWithMessageCredential" >
        <message clientCredentialType="UserName" />
      </security>
    </binding>
  </basicHttpBinding>
</extensions>

客户代码:

public class Activity1 : Activity
{
    private Button button;
    const string address = "https://.../IngredientService.svc/BasicHttp";

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);


        var timeout = new TimeSpan(0, 1, 0);
        var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential)
        {
            MessageEncoding = WSMessageEncoding.Text,
            Security =
            {
                Transport =
                {
                    ClientCredentialType = HttpClientCredentialType.None,
                    ProxyCredentialType = HttpProxyCredentialType.None
                },
                Message =
                {
                    ClientCredentialType = BasicHttpMessageCredentialType.UserName,
                }
            },
            HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
            MaxReceivedMessageSize = 655536,
            ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas
            {
                MaxArrayLength = 655536,
                MaxStringContentLength = 655536,
            },
            SendTimeout = timeout,
            OpenTimeout = timeout,
            ReceiveTimeout = timeout,
        };

        System.Net.ServicePointManager.ServerCertificateValidationCallback += OnServerCertificateValidationCallback;

        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.Main);

        // Get our button from the layout resource,
        // and attach an event to it
        button = FindViewById<Button>(Resource.Id.MyButton);

        button.Click += delegate
        {
            client = new IngredientServiceClient(binding, new EndpointAddress(address));
            var clientCredential = client.ClientCredentials.UserName;
            clientCredential.UserName = "admin";
            clientCredential.Password = "KDNSG7";

            client.BeginGetIngredients("e", callBack, null);
        };
    }

    IngredientServiceClient client;

    private void callBack(IAsyncResult ar)
    {
        var result = client.EndGetIngredients(ar);

        button.Text = result.First().Name;
    }

    private bool OnServerCertificateValidationCallback(object sender, X509Certificate certificate, 
                                                       X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        return true;
    }
}

这段代码在 WPF 中运行良好,返回结果,一切正常。我从旧线程中看到,WCF 仍处于开发周期的早期,但我只是想先检查一下我是否做错了什么。

【问题讨论】:

    标签: wcf web-services ssl xamarin.android


    【解决方案1】:

    要使您的服务在绑定不匹配的情况下仍能正常工作,您需要修改

    <security mode="TransportWithMessageCredential" enableUnsecuredResponse="true"  >
       <message clientCredentialType="UserName" />
     </security>
    

    我已经包含了上面示例中的整个 webconfig 以及添加的更改

     <service name="BrandDirector.ApplicationServer.Core.Services.UI.Products.Specifications.IngredientService" 
             behaviorConfiguration="CredentialValidation">
        <endpoint address="/BasicHttp"
            binding="basicHttpBinding"
            bindingConfiguration="BDBasicHttpBindingWithSecurity" 
            contract="BrandDirector.ApplicationServer.Core.Services.UI.Products.Specifications.IIngredientService" />
        <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
    </service>
    
    <behavior name="CredentialValidation">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
      <HttpStatusCode200Behavior />
      <serviceCredentials type="BrandDirector.ApplicationServer.Core.Security.Authentication.PasswordServiceCredentials, BrandDirector.ApplicationServer.Core.Security, Version=1.0.0.0, Culture=neutral">
        <userNameAuthentication userNamePasswordValidationMode="Custom"
          customUserNamePasswordValidatorType="BrandDirector.ApplicationServer.Core.Security.CredentialValidator, BrandDirector.ApplicationServer.Core.Security" />
      </serviceCredentials>
    </behavior>
    
    <extensions>
      <behaviorExtensions>
        <add name="HttpStatusCode200Behavior" type="BrandDirector.ApplicationServer.Core.Services.Common.ServiceModel.HttpStatusCode200BehaviorExtension, BrandDirector.ApplicationServer.Core.Services.Common" />
      </behaviorExtensions>
    
      <basicHttpBinding>
        <binding name="BDBasicHttpBindingWithSecurity" messageEncoding="Text" maxReceivedMessageSize="655536">
          <security mode="TransportWithMessageCredential" enableUnsecuredResponse="true"  >
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </basicHttpBinding>
    </extensions>
    

    【讨论】:

    • 请注意 enableUnsecuredResponse 不适用于 basicHttpBinding。不过,它适用于 customBinding。
    【解决方案2】:

    目前 MonoTouch 不支持 WS-Security 协议,该协议允许客户端在 SOAP 消息信封内发送凭据。但是,MonoTouch 确实支持通过指定适当的 ClientCredentialType 将 HTTP 基本身份验证凭据发送到服务器的能力。

    查看此页面: http://docs.xamarin.com/android/guides/Application_Fundamentals/Introduction_to_Web_Services

    【讨论】:

      【解决方案3】:

      我刚刚使用了 RestSharp 和一个将在服务器端进行身份验证的自定义身份验证标头内容。

      【讨论】:

        【解决方案4】:

        在我的例子中,在主机配置文件的 AudienceUris 标记中添加服务解决了同样的异常问题。

        <system.identityModel>
        ...
            <identityConfiguration>
            ...
                <audienceUris>
                    <add value="serviceName.svc" />
                </audienceUris>
            ...
            </identityConfiguration>
        ...
        </system.identityModel>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-30
          • 2011-03-02
          • 1970-01-01
          • 2017-08-23
          • 1970-01-01
          • 1970-01-01
          • 2016-09-23
          • 1970-01-01
          相关资源
          最近更新 更多