2008-11-17 18 views
1

我试图在PHP中使用SOAP扩展实现有状态的Web服务。 (是的,我知道Web服务应该是无状态的;我真正关心的是某种形式的会话ID,所以我不需要每次调用该服务都需要进行身份验证)。 PHP.net的API文档在这方面有点缺乏,并且没有其他的东西写在它上面。使用SOAP的有状态PHP Web服务

我找到了一个讨论它的页面(http://bytes.com/forum/thread160816.html)并将该代码作为测试实现。我构建了一个使用Web服务并调用每个函数并显示结果的小型.NET应用程序。从我读过的内容来看,只要使用setClass()函数将函数封装在类中,并且setPersistence()函数通过SOAP_PERSISTENCE_SESSION,PHP SOAP扩展就会在调用之间保持类变量。

这里是我的代码:

<?php 

class User 
{ 
    var $name = "Initial value"; 

    function setName($name) 
    { 
     $this->name = $name; 

     // Tried this too. 
     // $this->name = "Set to string constant" ; 
    } 

    function getName() 
    { 
     // This always returns "Initial value" 
     return $this->name; 
    } 
} 


// Tried placing session_start() in several places 
// before $server->handle()... 
// One guy says this doesn't need to be called. 
// I assume it depends on if session autostart is on. 
session_start(); 

$server = new SoapServer(null, array('uri' => 'http://localhost/')); 
$server->setClass('User'); 
$server->setPersistence(SOAP_PERSISTENCE_SESSION); 
$server->handle(); 

?> 

我遇到的问题是$名称不会调用之间仍然存在 - 我总是得到初始化值,而不是我给你价值的setName()。正如我所说的,我试图在对数据库进行身份验证后坚持会话ID - 如果有人有更好的方法来做到这一点,我愿意接受建议;不过,我仍然想解决一般情况。有人有主意吗?

回答

1

我真的解决了我自己的问题。

我工作的假设是:1).NET自动处理cookie;和2)我的问题是与PHP。情况也不是这样。我的PHP代码很好,但我需要添加一个元素到我的.NET代码来处理会话cookie。

实例化Web服务对象后,我需要将CookieContainer类的实例分配给Web服务对象。我的最终客户端代码如下:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 

namespace WsTest 
{ 
    public partial class PhpWsForm : Form 
    { 
     private localhost.MyWebService ws; 

     public PhpWsForm() 
     { 
      InitializeComponent(); 
      ws = new WsTest.localhost.MyWebService(); 

      // The line below is the part that I forgot! 
      ws.CookieContainer = new System.Net.CookieContainer(); 
     } 

     private void butSetVal_Click(object sender, EventArgs e) 
     { 
      ws.setName(txtSetVal.Text); 
     } 

     private void butGetVal_Click(object sender, EventArgs e) 
     { 
      txtGetVal.Text = ws.getName(); 
     } 
    } 
} 

无论如何还要谢谢!

0

大多数soap客户端为每个请求启动一个新的连接,所以没有“会话”。

如果您的SOAP服务可以在每个回复的SOAP信封中的某处发送会话ID,并要求客户端在每个后续请求上传递会话ID。

这样更好,因为您的客户现在已经掌握了对beheaviour的线索和控制。

+0

你能举个例子吗?我的意思是如何在服务器端恢复会话? – Cleankod 2011-03-25 19:18:00

0

要使用有状态的Web服务,需要在客户端的SOAP cookie中设置服务器会话的会话标识。默认情况下,每次发送SOAP请求时,服务器都会生成唯一的会话ID。为了防止在SOAP cookie中设置从第一个请求获得的会话ID。该cookie将随后发送您的所有肥皂电话。 例如,如果您正在使用SOAP,那么第一个WS调用后消耗了ASP.net web服务,得到了响应报头是这样的:

$client = SoapClient("some.wsdl", array('trace' => 1)); 
$result = $client->SomeFunction(); 
$headers = $client->__getLastResponseHeaders(); 

现在$headers必须包含会话ID与像“ASP的名称。 NET_SessionId”。获得从$headers的ID,并创建一个cookie如下:

//$client->__setCookie($cookieName, $cookieValue); 
$client->__setCookie('ASP.NET_SessionId', $cookieValue); 

现在从客户端的所有的SOAP请求会包含此会话ID和你的状态将持续到服务器上。