使用SOAP的有状态PHP Web服务

时间:2021-11-08 15:22:29

I'm trying to implement a stateful web service in PHP using the SOAP extension. (Yes I know that web services are supposed to be stateless; all I really care to persist is some form of a session ID so I don't need to authenticate with every call to the service). PHP.net's API documentation is somewhat lacking on this, and there isn't much else written on it.

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

I found one page that discusses it (http://bytes.com/forum/thread160816.html) and implemented the code as a test. I built a small .NET application that consumes the web service and calls each function and displays the result. From what I've read, the PHP SOAP extension will persist class variables between calls as long as the functionality is encapsulated in a class using the setClass() function and the setPersistence() function is passed SOAP_PERSISTENCE_SESSION.

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

Here is my code:

这是我的代码:

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

?>

The problem I run into is that $name is not persisted between calls -- I always get the initialized value and not the value I assign to setName(). As I stated, I'm trying to persist a session ID after authenticating against a database -- if anyone has a better way to do this I'm open to suggestions; however, I would still like to solve the general case. Anyone have any ideas?

我遇到的问题是$ name在调用之间没有持久化 - 我总是得到初始值而不是我赋给setName()的值。正如我所说的那样,我正在尝试在对数据库进行身份验证后保留会话ID - 如果有人有更好的方法来执行此操作,我会接受建议;但是,我仍然想解决一般情况。有人有主意吗?

3 个解决方案

#1


1  

I actually solved my own problem.

我实际上解决了自己的问题。

I was working under the assumptions that: 1) .NET handles cookies automatically; and 2) my problem was with the PHP. Neither was the case. My PHP code was fine but I needed to add one more element to my .NET code to handle the session cookie.

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

After instantiating the web service object, I needed to assign an instance of the CookieContainer class to the web service object. My final client side code is below:

在实例化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();
        }
    }
}

Thanks anyway!

#2


0  

Most soap clients start a new connection for each request so there is no "session".

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

If its your SOAP service you could send the session id somewhere inside in the SOAP envelope on every reply and ask the client to pass the session id on every subsequent request.

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

This is much nicer as your client now has clue and control over the beheaviour.

这是更好的,因为您的客户现在有线索和控制beheaviour。

#3


0  

For consuming the stateful web service, you need to set the session ID of the server session in the SOAP cookie on client side. By default each time SOAP request is sent, the server generates a unique session ID. To prevent that just set the session ID got from first request in SOAP cookie. That cookie will be sent with your all subsequent soap calls. FOr example if you are consuming an ASP.net webservice using SOAP, then after the first WS call, get the response headers like this:

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

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

Now $headers must contain the session ID with a name like 'ASP.NET_SessionId'. Get the ID from the $headers and create a cookie as follows:

现在$ headers必须包含名为“ASP.NET_SessionId”的会话ID。从$ headers获取ID并创建cookie,如下所示:

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

Now all the SOAP requests from your client will contain this session ID and your state will persist on the server.

现在,来自客户端的所有SOAP请求都将包含此会话ID,您的状态将保留在服务器上。

#1


1  

I actually solved my own problem.

我实际上解决了自己的问题。

I was working under the assumptions that: 1) .NET handles cookies automatically; and 2) my problem was with the PHP. Neither was the case. My PHP code was fine but I needed to add one more element to my .NET code to handle the session cookie.

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

After instantiating the web service object, I needed to assign an instance of the CookieContainer class to the web service object. My final client side code is below:

在实例化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();
        }
    }
}

Thanks anyway!

#2


0  

Most soap clients start a new connection for each request so there is no "session".

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

If its your SOAP service you could send the session id somewhere inside in the SOAP envelope on every reply and ask the client to pass the session id on every subsequent request.

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

This is much nicer as your client now has clue and control over the beheaviour.

这是更好的,因为您的客户现在有线索和控制beheaviour。

#3


0  

For consuming the stateful web service, you need to set the session ID of the server session in the SOAP cookie on client side. By default each time SOAP request is sent, the server generates a unique session ID. To prevent that just set the session ID got from first request in SOAP cookie. That cookie will be sent with your all subsequent soap calls. FOr example if you are consuming an ASP.net webservice using SOAP, then after the first WS call, get the response headers like this:

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

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

Now $headers must contain the session ID with a name like 'ASP.NET_SessionId'. Get the ID from the $headers and create a cookie as follows:

现在$ headers必须包含名为“ASP.NET_SessionId”的会话ID。从$ headers获取ID并创建cookie,如下所示:

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

Now all the SOAP requests from your client will contain this session ID and your state will persist on the server.

现在,来自客户端的所有SOAP请求都将包含此会话ID,您的状态将保留在服务器上。