I have a generic proof of concept WCF service that is using forms authentication to secure access. All works great when my client is .NET (vb code below)
Dim client As SupplierServiceClient = New SupplierServiceClient()
client.ClientCredentials.UserName.UserName = "[email protected]"
client.ClientCredentials.UserName.Password = "password"
Dim SupplierList As List(Of Supplier) = client.GetSuppliers()
but as I want this to interop w/ anyone who can do SOAP 1.1/1.2 - how would a PHP or Java client connect?
My WCF web.config is listed below (fyi)
<system.serviceModel>
<services>
<service name="SampleApplicationWCF.Library.SupplierService" behaviorConfiguration="NorthwindBehavior">
<endpoint address="" name="wsHttpSupplierService" contract="SampleApplicationWCF.Library.ISupplierService" binding="wsHttpBinding" bindingConfiguration="wsHttp"/>
<endpoint address="https://server/SampleApplicationWCF/SupplierService.svc/Basic" name="basicHttpSupplierService" contract="SampleApplicationWCF.Library.ISupplierService" binding="basicHttpBinding" bindingConfiguration="basicHttp"/>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="wsHttp">
<security mode="TransportWithMessageCredential">
<transport/>
<message clientCredentialType="UserName" negotiateServiceCredential="false" establishSecurityContext="true"/>
</security>
</binding>
</wsHttpBinding>
<basicHttpBinding>
<binding name="basicHttp">
<security mode="TransportWithMessageCredential">
<transport/>
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="NorthwindBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceAuthorization principalPermissionMode="UseAspNetRoles"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I managed to authenticate a PHP client, but not without some effort. At first, I tried the following:
$header = new stdClass;
$credentials = new stdClass;
$credentials->Username="myuser";
$credentials->Password="mypass";
$header->UsernameToken = $credentials;
$securityNamespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
$client->__setSoapHeaders($securityNamespace, 'Security', $header);
It didn't work. It seems that PHP5 (v5.3.5 in my case) has a bug preventing the namespace prefix from appearing inside nested header tags.
http://bugs.php.net/bug.php?id=48966
I ended up with:
<UsernameToken><Username>myuser</Username><Password>myuser</Password></UsernameToken>
instead of:
<o:UsernameToken><o:Username>myuser</o:Username><o:Password>myuser</o:Password></o:UsernameToken>
So, what I had to do was hardcoding the necessary XML in a variable. This is ugly but working:
$securityNamespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
$headerContent = "<o:Security xmlns:o=\"$securityNamespace\">
<o:UsernameToken>
<o:Username>myuser</o:Username>
<o:Password>mypass</o:Password>
</o:UsernameToken>
</o:Security>";
$headerVar = new SoapVar($headerContent, XSD_ANYXML, null, null, null);
$header = new SoapHeader($securityNamespace, 'o:Security', $headerVar);
$client->__setSoapHeaders(array($header));
I hope it will be helpful to someone. Bye!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With