douqian8238 2015-07-28 18:43
浏览 94

安全wcf(使用用户名密码验证器)不能从PHP客户端工作

I have construct a simple secured wcf with wsHttpBinding in .Net C# (framework 4.5) and consume it from .Net C# (also) client and every thing work fine. But when I try to consume It from php (5.5) client by calling a method from the wcs service, the client not work and it has entered in an infinite loop and not showing any error message, just looping.

a. The following is my wcf ServiceContract and OperationContract's:

namespace CenteralServices
{
    [ServiceContract]
    public interface IAdminServices
    {
        [OperationContract]
        int Add(int x, int y);
    }
}


b. The following is the configueration file Web.config for the wcf:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
        <services>
            <service name= "CentralTicketServicesSystem.AdminSystem" 
                behaviorConfiguration="customBehaviour">
                <endpoint address="AdminServices" 
                        binding="wsHttpBinding" 
              contract="CentralTicketServicesSystem.IAdminServices"
              bindingConfiguration="ServiceBinding"
              behaviorConfiguration="MyEndPointBehavior">
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8080/AdminServicesSystem" />
      </baseAddresses>
    </host>
  </service>
</services>

<bindings>
  <wsHttpBinding>
    <binding name="ServiceBinding"
             openTimeout="00:10:00"
             closeTimeout="00:10:00"
             receiveTimeout="00:10:00"
             sendTimeout="00:10:00">
      <security mode="Message" >
        <message clientCredentialType="UserName"/>
      </security>

    </binding>
  </wsHttpBinding>
</bindings>

<behaviors>
  <endpointBehaviors>
    <behavior name="MyEndPointBehavior">
    </behavior>
  </endpointBehaviors>
  <serviceBehaviors>
    <behavior name="customBehaviour">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="false"/>
      <serviceAuthorization principalPermissionMode="Custom">
        <authorizationPolicies>
          <add policyType="CentralServicesHost.AuthorizationPolicy, CentralServicesHost" />
        </authorizationPolicies>
      </serviceAuthorization>
      <serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom"
           customUserNamePasswordValidatorType="CentralServicesHost.UserAuthentication, CentralServicesHost"/>
        <serviceCertificate findValue="15 63 10 5e b6 4b 4d 85 4b 2e 4d 5b ec 85 02 ec"
                            storeLocation="LocalMachine"
                            x509FindType="FindBySerialNumber"
                            storeName="My"/>
      </serviceCredentials>
    </behavior>
    <behavior name="mexBehaviour" >
      <serviceMetadata httpGetEnabled="true" />
    </behavior>

            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>



c. The following is UserAuthentication class:

namespace CentralServicesHost
{
    public class UserAuthentication : UserNamePasswordValidator
    {

        public override void Validate(string userName, string password)
        {
            if (string.IsNullOrEmpty(userName))
                throw new ArgumentNullException("userName");
            if (string.IsNullOrEmpty(password))
                throw new ArgumentNullException("password");

            if (userName != "test" && password != "test")
                 throw new FaultException("Unknown Username or Incorrect Password.");
        }
    }
}



d. The following is AuthorizationPolicy class:

namespace CentralServicesHost
{
    public class AuthorizationPolicy : IAuthorizationPolicy
    {
        Guid _id = Guid.NewGuid();
        // this method gets called after the authentication stage
        public bool Evaluate(EvaluationContext evaluationContext, ref object state)
        {
            // get the authenticated client identity
            IIdentity client = GetClientIdentity(evaluationContext);
            // set the custom principal
            evaluationContext.Properties["Principal"] = new CustomPrincipal(client);
            return true;
        }
        private IIdentity GetClientIdentity(EvaluationContext ec)
        {
            object obj;
            if (!ec.Properties.TryGetValue("Identities", out obj))
                throw new Exception("No Identity found");
            IList<IIdentity> identities = obj as IList<IIdentity>;
            if (identities == null || identities.Count <= 0)
                throw new Exception("No Identity found");
            return identities[0];
        }

        public System.IdentityModel.Claims.ClaimSet Issuer
        {
            get { return ClaimSet.System; }
        }

        public string Id
        {
            get { return _id.ToString(); }
        }
    }
}



e. The following is CustomPrincipal class:

namespace CentralServicesHost
{
    class CustomPrincipal : IPrincipal
    {
        IIdentity _identity;
        string[] _roles;

        public CustomPrincipal(IIdentity identity)
        {
            _identity = identity;
        }

        // helper method for easy access (without casting)
        public static CustomPrincipal Current
        {
            get
            {
                return Thread.CurrentPrincipal as CustomPrincipal;
            }
        }

        public IIdentity Identity
        {
            get { return _identity; }
        }

        // return all roles
        public string[] Roles
        {
            get
            {
                EnsureRoles();
                return _roles;
            }
        }

        // IPrincipal role check
        public bool IsInRole(string role)
        {
            EnsureRoles();
            return (_roles != null) ? _roles.Contains(role) : false;
        }

        // read Role of user from database
        protected virtual void EnsureRoles()
        {
            using (var s = new SupportedMaterialsSystemEntities())
            {
                _roles = new string[1] { "admin" };
            }
        }
    }
}

f. The following is my php client code:

<?php
$options = array('soap_version' => SOAP_1_2, 
                  'login'      =>  'test',
                  'password'   =>  'test');
$wsdl = "http://localhost:8080/AdminServicesSystem";
$client = new SoapClient($wsdl, $options);
$obj = new stdClass;
$obj->x = 3;
$obj->y = 3;
$retval = $client->Add($obj);//here the browser loops for infinite without any response.
//var_dump($exc);//THIS POINT NOT REACHED
//die();
$result = $retval->AddResult;
echo $result;

NOTES:
1. My OS is Win. 8.1, and I'm using visual studio 2013 (as adminstrator) and php Wamp Server.
2. I tried both, hosting the wcf service in IIS 6.2 and console application but non of them changes my php client looping.
3. I have Created the self-signed certificate usin the IIS manager that stores it in my local machine.
4. When I change the soap_version in the php code from SOAP_1_2 to SOAP_1_1 I had Cannot process the message because the content type 'text/xml; charset=utf-8' was not the expected type 'application/soap+xml; charset=utf-8'..

Last Note:
My .Net C# Client code is the following:

 using (var svcProxy = new AdminServiceProxy.AdminServicesSystemClient())
        {
            svcProxy.ClientCredentials.UserName.UserName = "test";
            svcProxy.ClientCredentials.UserName.Password = "test";
            Console.WriteLine(svcProxy.Add(1, 1));//the service works fine and print 2
        }
 }


So agin, What is the right way to call a secured wcf (with wsHttpBinding) service from php.

  • 写回答

1条回答 默认 最新

报告相同问题?

悬赏问题

  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100
  • ¥15 关于#hadoop#的问题