ghedipunk / PHP-Websockets

A Websockets server written in PHP.
BSD 3-Clause "New" or "Revised" License
913 stars 375 forks source link

How to pass client cookies to the websocket server? #107

Closed Nikola-Obreshkov closed 6 years ago

Nikola-Obreshkov commented 6 years ago

When I print the $buffer in function doHandshake I can see the PHP session cookie of the client. Something like: Cookie: PHPSESSID=4muqlmg4sgknkhvfed2pc1rri2 But if I set a client cookie manually with: if ( !isset($_COOKIE['foo']) ) setcookie('foo', 'bar'); I do not receive it on the sever. What am I doing wrong?

ghedipunk commented 6 years ago

Once the handshake is over, the WebSocket connection has nothing to do with the HTTP protocol any more.

Thus, an open socket can not receive additional cookies, and the server can not set additional cookies from the WebSocket server.

If you want to set up a new cookie based on information in your WebSocket application, you need to do so in Javascript.

If you need to make the WebSocket application on your server aware of changes to the cookies, you need to pass that information through the socket, or you need to disconnect and re-connect after using Javascript to set the new cookie.

Nikola-Obreshkov commented 6 years ago

Maybe I was not clear. After I set the cookie on the client I refresh the browser several times to produce new handshakes. But on the server I receive only the PHP session cookie and not the cookies I set by mysefl .

ghedipunk commented 6 years ago

Are you sure that you set the cookie on the client?

The only code that I'm seeing that sets a cookie is if ( !isset($_COOKIE['foo']) ) setcookie('foo', 'bar');

That's PHP code, not Javascript; not client side code.

In order for the setcookie() function to work, it needs to be able to modify headers to an HTTP reply (which is why it also won't work if you have output buffers off and you've already sent page contents before calling that function). There is no such thing as an HTTP header inside of a WebSocket message, so the browser itself doesn't know to look for cookies in websocket messages, and wouldn't try to set a cookie even if it did see one.

https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie

Server side:

protected function connected ($user) {
    $this->send('set the cookie');
}

Client side:

socket.onmessage = function(msg) { 
    if (msg.data == 'set the cookie') {
        document.cookie = 'foo=bar';
    } 
};
Nikola-Obreshkov commented 6 years ago

I am setting the cookie on the client. Even with PHP code the cookie is added automatically to the document.cookie. If you do with PHP: if ( !isset($_COOKIE['foo']) ) setcookie('foo', 'bar'); and then in JavaScript (even without refresh): alert(document.cookie); you will see that there is: foo=bar; The problem was that when I set the cookie it needs expire time and path in order to be added to the headers. It doesn't matter whether PHP: if ( !isset($_COOKIE['foo']) ) setcookie('foo', 'bar', time() + 3600, '/'); or JavaScript: var time = new Date().getTime() + 3600 * 1000; document.cookie = 'foo=bar; expires=' + time.toUTCString() + '; path=/'; in doHandshake($user, $buffer) when printing the $buffer I can finally see: Cookie: PHPSESSID=4muqlmg4sgknkhvfed2pc1rri2; foo=bar @ghedipunk thank you for the assistance! 👍