开发者

WP7 + WCF + IIS + HTTPS (Transport) + Basic Authentication

I've read a lot of posts about the problem to use WP7 + WCF (IIS 7) over HTTPS with basic authentication but I'm still in trouble with it...

If I just use HTTPS transport without BasicAuth it works like a charm. But both combinated doesn't work for me...

Maybe you can help me to identify my failure...

My ClientConfig:

<configuration>
<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IService1" maxBufferSize="2147483647"
                maxReceivedMessageSize="2147483647">
              <security mode="Transport" />
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint 
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1"
            contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" />
    </client>
</system.serviceModel>

My ServiceConfig:

    <?xml version="1.0"?>
<configuration>
  <appSettings/>
  <system.web>
    <compilation debug="true" targetFramework="4.0"/>
    <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WP7.CustomUserNameValidator, WP7" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <bindings>
      <basicHttpBinding>
        <binding maxReceivedMessageSize="2147483647"> 
          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
          <security mode="TransportWithMessageCredential" >
            <transport clientCredentialType="Basic"/>
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

My CustomUserNameValidator used in Service:

namespace WP7
{
public class CustomUserNameValidator : UserNamePasswordValidator
    {
        // This method validates users. It allows in two users, 
        // test1 and test2 with passwords 1tset and 2tset respectively.
        // This code is for illustration purposes only and 
        // MUST NOT be used in a production environment because it 
        // is NOT secure.
        public override void Validate(string userName, string password)
        {

            if (null == userName || null == password)
   开发者_如何学运维         {
                throw new ArgumentNullException();
            }

            if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset"))
            {
                throw new FaultException("Unknown Username or Incorrect Password");
            }
        }
    }
}

The code in my Wp7 App to call a method a sync (with a solution from: http://cisforcoder.wordpress.com/2010/12/01/how-to-implement-basic-http-authentication-in-wcf-on-windows-phone-7/#comment-174):

proxy = new ServiceReference1.Service1Client();
            proxy.Endpoint.Address = new System.ServiceModel.EndpointAddress(new Uri(Details.mySettings.EndpointAddress));

            proxy.PingServerCompleted += new EventHandler<ServiceReference1.PingServerCompletedEventArgs>(proxy_PingServerCompleted);

            var credentials = EncodeBasicAuthenticationCredentials("test1", "1tset");

            using (OperationContextScope scope =
                      new OperationContextScope(proxy.InnerChannel))
            {
                HttpRequestMessageProperty request = new HttpRequestMessageProperty();
                request.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " + credentials;

                OperationContext.Current.OutgoingMessageProperties.Add(
                                                   HttpRequestMessageProperty.Name, request);
                proxy.PingServerAsync(myServer);
            }

private string EncodeBasicAuthenticationCredentials(string username, string password)
        {
            //first concatenate the user name and password, separated with :
            string credentials = username + ":" + password;

            //Http uses ascii character encoding, WP7 doesn’t include
            // support for ascii encoding but it is easy enough to convert
            // since the first 128 characters of unicode are equivalent to ascii.
            // Any characters over 128 can’t be expressed in ascii so are replaced
            // by ?
            var asciiCredentials = (from c in credentials
                                    select c <= 0x7f ? (byte)c : (byte)'?').ToArray();

            //finally Base64 encode the result
            return Convert.ToBase64String(asciiCredentials);
        }

Furthermore I've already set "Basic Authentication" setting in the IIS Virtual Directory to "Enabled".

Everytime I've got some different error exceptions: either CommunicationException or SecurityException or what else...

Someone an idea which might be solve my problem?

Thanks. Jason


The client needs to also specify the clientCredentialType - that's missing from the client config. So the client isn't expecting to have to send credentials but the service is expecting them

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜