I have a self-hosted wcf service that just adds 2 numbers and returns the value. It works fine, but I am not sure how I can send the username and password through the php client, so it will validate against my CustomUserNamePasswordValidator. Here is the implementation for the Add Method:
public class MathService : IMathService
{
public double Add(double x, double y)
{
return x + y;
}
}
Here is my current App.Config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="WcfWithPhp.MathService">
<endpoint address="" binding="basicHttpBinding" contract="WcfWithPhp.IMathService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/MathService" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
I am starting the service like this:
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(WcfWithPhp.MathService));
host.Open();
Console.WriteLine("Math Service Host");
Console.WriteLine("Service Started!");
foreach (Uri address in host.BaseAddresses)
{
Console.WriteLine("Listening on " + address);
}
Console.WriteLine("Press any key to close the host...");
Console.ReadLine();
host.Close();
}
For the php client, I am doing:
<?php
header('Content-Type: text/plain');
echo "WCF Test\r\n\r\n";
// Create a new soap client based on the service's metadata (WSDL)
$client = new SoapClient("http://localhost:8731/MathService?wsdl");
$obj->x = 2.5;
$obj->y = 3.5;
$retval = $client->Add($obj);
echo "2.5 + 3.5 = " . $retval->AddResult;
?>
The above works fine without authentication, but I want to be able to authenticate the username and password from the phpclient. When they try to access my service, I want the username and password to validate through the overriden Validate method of the UserNamePasswordValidator, which is currently defined as:
public override void Validate(string userName, string password)
{
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("userName");
if (string.IsNullOrEmpty(password))
throw new ArgumentNullException("password");
// check if the user is not test
if (userName != "test" || password != "test")
throw new FaultException("Username and Password Failed");
}
I am just using test and test as an example for the username and password. I know I have to set the modify the behavior configuration and do a binding configuration, so the service will use the CustomUserNamePasswordValidator, but since I don't know PHP, I am not sure how to send the credentials from php to the wcf service and once the credentials are sent, I don't know how to set it in the wcf service. I am not creating a wcf service. I thought I could do client.ClientCredentials.UserName.UserName
and client.ClientCredentials.UserName.Password
, but this is only if I am creating .NET client which I am not.
Another question I had was that if the client is a php client, am I restricted to only basicHttpBinding?
Also, ideally what I would like to do is send a soap request from the php client to the wcf service, so if anyone can point me in the right direction for this, it would be great.
I just tried the following, but it didn't work (Add was called, but it wasn't authenticated)
$sh_param = array('userName' => 'test', 'passWord' => 'test2');
$headers = new SoapHeader('http://localhost:8731/MathService.svc','UserCredentials',
$sh_param,false);
$client->__setSoapHeaders(array($headers));
UPDATE: My PHP Soap Client initialization is now:
$client = new SoapClient('http://localhost:8731/MathService?wsdl',
array('login' => "test2",
'password' => "test",
'trace'=>1));
By doing the above, it added the following in the Request:
`Authorization: Basic dGVzdDI6dGVzdA==`
However, my wcf service which is hosted in a console app, is not picking up this authorization, I have a custom username validator which has a hard-coded value of test for the username and test for the password, but when I try "test2" for the login, it is still calling the method. I am using TransportWithCredentialOnly and Message="UserName"
Try SoapClient constructor overload:
$client = new SoapClient("some.wsdl", array('login' => "some_name",
'password' => "some_password"));
And here is the doc: http://www.php.net/manual/pl/soapclient.soapclient.php