How can I get $_SESSION data from SESSID?

2019-06-18 15:27发布

问题:

I have a PHP websocket server (https://github.com/lemmingzshadow/php-websocket/).

When an user connects, I want to set/get some session data.

The problem is that I can't use $_SESSION because if I do that, instead of clients' session I get the session of my websocket server.

I have managed to get clients' SESSID:

private function handshake($data) { 
    $this->log('Performing handshake');  
    if(preg_match("/PHPSESSID=(.*?)(?:;|\r\n)/", $data, $matches)){
        $sessid = $matches[1];
    }
    /* Do handshake */
}

But now I don't know how to get the session data related to that SESSID.

回答1:

It seems I have solved it (but I have to test it more):

private function handshake($data) { 
    $this->log('Performing handshake');
    if(preg_match("/PHPSESSID=(.*?)(?:;|\r\n)/", $data, $matches)){
        $this->sessID = $matches[1];
        session_id($this->sessID);
        @session_start();
        if(isset($_SESSION['userName'])){
            $this->userName = $_SESSION['userName'];
        }else{
            $_SESSION['userName'] = $this->userName;
        }
        session_write_close();
    }else{
        $this->log('No SESSID');    
        return false;
    }
    /* Do handshake */
}

And to enable session cookies, on my client page index.php

<?php
session_start();
?>
<!DOCTYPE html>
<!-- Page's HTML -->

Explanation

First, I use session_id so that the following session_start() will give me the session related to the given SESSID.

Then, I can use @session_start() to start the session. It needs @ because the websocket server has already started, so not using it produces:

  • PHP Warning: session_start(): Cannot send session cookie - headers already sent
  • PHP Warning: session_start(): Cannot send session cache limiter - headers already sent

Now I can do what I want with $_SESSION.

Finally, I use session_write_close() in order to close the session. It must be used because:

  • session_id must be called before session_start(). If the session isn't closed, when a second client connects, a session will be already open, so session_id won't work.

  • To avoid session locking. As @Sven said, there can only be one instance of PHP running that has access to the session file. Since the websocket server's script should be running for a long time, once it opens a session, you can't use session in other scripts if you don't close it.