如何将用户名/密码凭据从php客户端传递到自托管的wcf服务?

时间:2011-05-19 13:34:49

标签: c# php wcf wcf-authentication

我有一个自托管的wcf服务,只添加2个数字并返回值。它工作正常,但我不知道如何通过php客户端发送用户名和密码,因此它将验证我的CustomUserNamePasswordValidator。以下是添加方法的实现:

public class MathService : IMathService
{
    public double Add(double x, double y)
    {
        return x + y;
    } 
}

这是我目前的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>

我正在开始这样的服务:

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();
}

对于php客户端,我正在做:

<?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;

?>

以上工作正常,无需身份验证,但我希望能够从phpclient验证用户名和密码。当他们尝试访问我的服务时,我希望用户名和密码通过UserNamePasswordValidator的重写Validate方法进行验证,该方法当前定义为:

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");
 }

我只是使用测试和测试作为用户名和密码的示例。我知道我必须设置修改行为配置并执行绑定配置,因此服务将使用CustomUserNamePasswordValidator,但由于我不知道PHP,我不知道如何将凭据从php发送到wcf服务和一旦凭证被发送,我不知道如何在wcf服务中设置它。我不是在创建一个wcf服务。我以为我可以做client.ClientCredentials.UserName.UserNameclient.ClientCredentials.UserName.Password,但这只是在我创建.NET客户端时,我不是。

我遇到的另一个问题是,如果客户端是php客户端,我是否仅限于basicHttpBinding?

另外,理想情况下,我想要做的是从php客户端向wcf服务发送一个soap请求,所以如果有人能指出我正确的方向,那就太棒了。

我刚刚尝试了以下内容,但它无法正常工作(已调用添加,但未经过身份验证)

$sh_param = array('userName' => 'test', 'passWord' => 'test2');

$headers = new SoapHeader('http://localhost:8731/MathService.svc','UserCredentials',   
$sh_param,false);

$client->__setSoapHeaders(array($headers));

更新: 我的PHP Soap客户端初始化现在是:

$client = new SoapClient('http://localhost:8731/MathService?wsdl',
                         array('login' => "test2", 
                               'password' => "test",
                               'trace'=>1));

通过以上操作,它在请求中添加了以下内容:

`Authorization: Basic dGVzdDI6dGVzdA==`

但是,我在控制台应用程序中托管的wcf服务没有获得此授权,我有一个自定义用户名验证器,其中包含用户名和测试密码的硬编码值test,但是当我尝试“test2”登录,它仍在调用方法。我正在使用TransportWithCredentialOnly和Message =“UserName”

1 个答案:

答案 0 :(得分:4)

尝试SoapClient构造函数重载:

$client = new SoapClient("some.wsdl", array('login'    => "some_name",
                                            'password' => "some_password"));

以下是文档:http://www.php.net/manual/pl/soapclient.soapclient.php