Home > Flash Platform, Zend_Amf > Zend Amf now with php session support

Zend Amf now with php session support

December 30th, 2008

PHP session support is now enabled through the Zend Amf. To get started you need to update your Zend_Amf_Server class from the repository. You will also need to make sure you have Zend_Session for those of you that are using the framework on as use-at-will bases.

Once you have updated your server you will need to also update your bootstrap/endpoint file to start using sessions and tell Zend Amf to use sessions.

$server = new Zend_Amf_Server();
Zend_Session::start();
$server->setSession();

You now have session support for all of your services.

A session example
We are going to create the following example in order to showcase how sessions can be used in an application.

Flex zend amf php session example

Flex zend amf php session example

The flex application connects to this SessionTest a service that opens a session count variable that is incremented with the getCount method. There are also three utility methods to show how sessions are being handled. The method getSessionID returns the current php session id. The method updateSessionID tells php to regenerate the sessions id. Finally unregister destroys the count session variable to start the incrimination over on the next service call.

/**
 * Example class for sending a session back to ActionScript.
 */
class SessionTest
{
	/** Check if the session is available or create it. */
	public function __construct() {

		if (!isset($_SESSION['count'])) {
			$_SESSION['count'] = 0;
		}
	}

	/** increment the current count session variable and return it's value */
    public function getCount()
    {
    	$_SESSION['count']++;
    	return $_SESSION['count'];
    }

    /** return the php session id value */
    public function getSessionID()
    {
    	return session_id();
    }

    /** Tell's php to generate a new session id */
    public function updateSessionID()
    {
    	session_regenerate_id();
    }

    /** clear the refrence to the count session variable */
    public function unregister() {
    	unset($_SESSION['count']);
    	return true;
     }
}

The flex code just consists of calls to the remote methods. There is nothing that you need to do special in your ActionScript in order to handle sessions. Note that there are just methods and handlers for all of the service calls.



    
        
        	
        	
        	
        	
        
    
    


	

Sessions are used for state but Flex is state-full?
Using sessions is important for storing state on the server. This can be hard to wrap your head around when to store state in the client and sync that state with the server. My recommendation is that you should use sessions when you don’t trust the client or that the data is so important that you shouldn’t ever trust the client. Using sessions with Zend_ACL and Zend_Auth are great examples of when you want to keep state in client and validate that state in the server. If something changes that was not intentional invalidate the state and log the customer out.

Session Identifiers

This is import to do as frequently as you can in you application. A new session ID can decrease the ability for a cross site scripting attack to take over your session and become a logged in user. In this example I have used a php call but make sure that you check out the documentation on Zend Session and specifically Zend_Session::regenerateId()

A primary difference between an RIA written in Flex, ajax, etc is that it does not reload the browser. This means that the user can aggressively click on a button and the RIA does not have the new session id returned. You can start “loosing” data as the new call is being sent with an old session id. If you application has aggressive click make sure you test regeneration speeds with slow connections. A proxy tools such as charles can really help debug slow connections.

At a minimal regenerate an id on massive state changes of the application! Login, logout, privilege escalation, etc.

Click around on the demo below to see what I mean!

Session Example

Finally
Give me your feedback. Sessions will be in the next minor so there is still time to change things, document better, and make more examples. Have fun!

Flash Platform, Zend_Amf

  1. Adnan Doric
    December 31st, 2008 at 06:15 | #1

    Hello Wade :)

    I am not very good at PHP so I am a bit confused: I don’t know why you are using __construct() method for PHP4 compatibility knowing that Zend Framework is for PHP5 only ?

    Please correct me if I’m wrong.
    Cheers

  2. Adnan Doric
    December 31st, 2008 at 06:23 | #2

    Well ok I’m wrong, __construct is PHP5 only, sorry for this useless comment :)

  3. Bunal
    December 31st, 2008 at 06:53 | #3

    Great,

    It’s offtopic but:

    I’ve been trying to use serverside remoting in FMS3 with ZendAMF but no luck.

    I get “onStatus>info.code: Client.Header.BadVersion” in FMSLiveLog

    But when i try to use the samegateway with Flex there is np and eveything works smooth.

    Thought it might be smthing related to amf version but FMS3 should also use AMF3?

    Any help would be appreciated much.

  4. December 31st, 2008 at 10:31 | #4

    @Adnan Doric With PHP 4 EOL and there not being any security updates even real soon I consider php 4 as dead as php 3.

  5. December 31st, 2008 at 10:31 | #5

    @Bunal I have not tried it yet. Can you open a bug ticket and we will get it figured out.

  6. Bunal
    January 2nd, 2009 at 04:26 | #6

    Wade, does ZendAMF supports AMF0 also. I know AMF0 is a subset of AMF3 so it should handle? Or is there any properties that can be added to gateway php file so zendAMF only uses the AMF0?

    There is a note in the server-side AS docs that says:
    Note: The server always serializes data in AMF0 while executing Flash Remoting functions.

  7. January 2nd, 2009 at 09:44 | #7

    @Bunal You are correct in stating that AMF0 is a superset of amf3. This means that every first request is AMF0 until it encounters and AMF3 object. At that point everything is always parsed by AMF3. If you are sending data from flex it is “always” amf3 because remoteobeject wraps the data inside and AMF3 object. Even if you send an array it has to parse the outer object first. If you send data with a netconnection even if you explicity tell it to use AMF3 it will still use AMF0 until it encounters and AMF3 object.
    Hope that helps!

  8. mystikum
    January 10th, 2009 at 17:10 | #8

    sorry, but I am not clear on how flex is interacting with zend, is it accessing it through source=”SessionTest”?

  9. January 12th, 2009 at 10:05 | #9

    @mystikum The endpoint in the remoteobject tag is pointing at the Zend Amf gateway url. SessionTest is the remote php class that we are calling

  10. mystikum
    January 12th, 2009 at 16:59 | #10

    Thanks, I got this working,
    One thing to note is that i had to take out, “$server->setSession()” in order for it to work. I am not sure why.

    Thanks for the great tutorial

  11. January 12th, 2009 at 21:06 | #11

    @mystikum I have no idea how that could have possibly worked without setsession included.

  12. mystikum
    January 12th, 2009 at 22:11 | #12

    @wadearnold
    this is the error i get in flex when I try it with the setSession()
    code:
    Client.Error.MessageSend

    Message:
    Send failed

    Detail:
    Channel.Connect.Failed error NetConnection.Call.BadVersion: : url: ‘http://127.0.0.1/amf/index.php’

    it doesn’t occur at all when I exclude that code though…

  13. Elango
    February 3rd, 2009 at 03:18 | #13

    Hi,

    Can we have the source for this example showed on this page.

    Thanks

  14. February 7th, 2009 at 10:56 | #14

    Wade,
    The 1.7 download on http://framework.zend.com/ does not contain the latest AMF release, I had to download from svn.
    In case anyone downloaded from the framework site and is recieving “Channel.Connect.Failed error”

  15. February 9th, 2009 at 10:30 | #15

    We are working on getting everything merged into the 1.7.4 release that should be out this week.

  16. February 10th, 2009 at 16:22 | #16

    @Elango Looks like my worpress plugin crapped out. It’s fixed now.

  17. February 14th, 2009 at 10:30 | #17

    Thanks wade,

    this works as expected. I didn’t find the session code changes you made in the tagged 1.7.5 repo. I had to get trunk instead for my testing.

  18. Artur Borodziej
    February 17th, 2009 at 17:00 | #18

    I wonder why why everyone had problems with $server->setSession(); method ;)

  19. Al
    February 21st, 2009 at 13:28 | #19

    [FaultEvent fault=[RPC Fault faultString="Duplicate method registered: ....etc.

    in http://framework.zend.com/svn/framework/standard/trunk/library/Zend/Amf/Server.php

  20. Al
    February 21st, 2009 at 17:24 | #20

    So strange….

    in MyService.php

    public function login(…

    >>FaultEvent “Duplicate method registered…”

    I have changed it to (in Flex and PHP):

    public function mylogin(…

    >>OK

    ??? where is the bug??!! I lost 4 hours on Saturday to fix!!!! :( (((( YIiiAAAA!!! I hate computer science!!!!

  21. February 22nd, 2009 at 23:42 | #21

    I am using Zend Framework 1.74. The setSession() method does not exist in the Zend_Amf_Server class or anywhere in the Zend/Amf folder. What am I missing? Thanks! David

  22. February 23rd, 2009 at 08:57 | #22

    Sorry, I fixed my problem by re-reading the 1st line in your post. I also downloaded 1.75 and noticed that setSession() still isn’t included. I have this working now.

  23. conor
    March 7th, 2009 at 17:14 | #23

    hey Wade, I’m trying to add session support to my AMF application using this tutorial. When I modify my bootstrap file to include the line:

    $server->setSession();

    I get an error back from the server which says:

    Fatal error: Call to undefined method Zend_Amf_Server::setSession() in localhost/amf/index.php on line 14

    Here is my bootstrap file:

    setSession();
    //adding our class to Zend AMF Server
    $server->setClass(”MyService”);
    $server->setClassMap(”VOLoad”, “VOLoad”);
    $server->setClassMap(”VOUser”, “VOUser”);
    $server->setProduction(false);
    echo( $server -> handle() );

  24. conor
    March 7th, 2009 at 17:16 | #24

    oops, code is obviously filtered somehow, here’s another go at my bootstrap file:

    //error_reporting(E_ALL|E_STRICT);
    ini_set(”display_errors”, “on”);
    ini_set(”include_path”, ini_get(”include_path”) . “:../../frameworks”);

    require_once ‘Zend/Amf/Server.php’;
    require_once ‘Zend/Session.php’;
    require_once ‘MyService.php’;
    //instantiating the zend server
    $server = new Zend_Amf_Server();
    //starting the zend session
    Zend_Session::start();
    $server->setSession();
    //adding our class to Zend AMF Server
    $server->setClass(”MyService”);
    $server->setClassMap(”VOLoad”, “VOLoad”);
    $server->setClassMap(”VOUser”, “VOUser”);
    $server->setProduction(false);
    echo( $server -> handle() );

  25. Mike
    March 11th, 2009 at 18:56 | #25

    I’m having the same issue as conor. How can I resolve this?

  26. Mike
    March 21st, 2009 at 19:27 | #26

    Again, despite the fact that I have updated the ZEND_AMF Server class with the code from the SVN repositor as mentioned in the article, I still get the same annoying “Fatal error: Call to undefined method Zend_Amf_Server::isSession() in /var/web/htdocs/core/application/default/controllers/ServicesController.php on line 84″ error.

    This has been holding my development hostage for over a week now, and is getting serious frustrating. Can anyone throw me a bone on this one?

  27. March 24th, 2009 at 00:43 | #27

    @conor
    your bootstrap file seems to say:
    setSession();
    and not
    $server->setSession();

  28. March 24th, 2009 at 00:44 | #28

    @Mike @Conor are you using the code from the trunk? I just migrated the code into the next 1.7 release. Mike i fired you an email.

  29. Mike
    March 31st, 2009 at 16:47 | #29

    I wanted to add a quick update to what the cause of my problem was:
    Running on Ubuntu 8.10, I had different versions of ZF installed in multiple locations, some belonged to the old installation of ZendStudio 6.1.0, some to the new installation of ZS 6.1.1 and some standalone versions I had for testing.

    For some reason PHP was looking at multiple directories, and not choosing the local installation of ZF under /library/Zend. After deleting all the additional ZF instances everything started to work as expected.

    -Mike

  30. roman
    April 24th, 2009 at 06:43 | #30

    Hi, I created small test application using Zend_Auth and Zend_ACL but had some troubles with it. Finnaly looked over Zend_Amf_Server code. (ZF is v1.7.8). I’m wondering why Zend_Amf_Server code uses php session handling function directly instead of Zend_Session and Zend_Session_Namespace (what about session validators and all “cool” staff of Zend_Session?!)

    look at handle method starting at line 380. is it secure?!

    if ($this->isSession()) {
    // Check if a session is being sent from the amf call
    if (isset($_COOKIE[$this->_sessionName])) {
    session_id($_COOKIE[$this->_sessionName]);
    }
    }

    look at line 102
    protected $_sessionName = ‘PHPSESSID’;

    and there is no no setter (or configuration option) to change this value. the only solution is to extend Zemd_Amf_Server with override. why?!

    now look at line 96
    protected $_sesionNamespace = ‘zend_amf’;

    and than look at setSession method. i’m bit confused why Zend_Session_Namespace is instantiated here?! to call session_start() indirectly trought Zend_Session::start()?! but, as you can see, Zend_Session and Zend_Session_Namespace isn’t used by the rest of server code. so, we have to stay with plain php session handling function or use Zend_Session_*. don’t mix it!

  31. nielsenx
    April 30th, 2009 at 21:45 | #31

    The session example thing isn’t working for me, it never gets incremented, I’m using safari on mac but I don’t think that should be a reason. Also I have a flash site using ZF to authenticate users and store a session and I can’t seem to keep that session data between flash amf calls, it doesn’t know that Zend_Auth is already set.

  32. nielsenx
    May 2nd, 2009 at 13:28 | #32

    I tried creating the same example you have using flash instead of flex and I’m getting consistent results with what I see in your example, the number is never updated because a new session ID is given everytime the amf call is made, is there something I’m missing?

  33. May 14th, 2009 at 06:11 | #33

    Hi Wade,
    Your example doesn’t work. I got my script to work but I get that line in my gateway file (where echo $server->handle(); is):
    AppendToGatewayUrl+?PHPSESSID=3fd770e188676605437223ab67c65370

    Is that normal?

    Thanks for your work!

  34. saltamontez
    January 25th, 2010 at 10:42 | #34

    Your example doesn´t work Firefox 3.5.7 and IE 8.8.76 so it seems. The flex example code is not displayed either. I´m really trying to make ends meet here but no luck. I put my AMF endpoint under an indexAction in my AmfController. I tweaked the code generated by Flashbuilder (gateway.php) so I can use the data-centric-development features. I got everything running so far but the session keeps getting lost.

  1. January 10th, 2009 at 22:43 | #1
  2. January 26th, 2009 at 06:45 | #2