I have a PHP Ratchet WebSocket server, running a custom chatroom on my website.
I would like to get the user's cookies when they connect to the server, so that I can get their session data and do something special if they are logged in / have specific permissions / etc.
In other posts (both on StackOverflow and otherwise), it is said that to get session data, you must get the client's cookies, which are supplied in their requests to the web server. The following line of code is meant to do this:
$conn->WebSocket->request->getCookies()
Where $conn is a ConnectionInterface.
My problem is, that when run this simply returns an empty array, even though the DevTools will show that there are indeed cookies.
Why might this not be returning a value?
just in case you're still searching for a solution:
1.In case your cookies only valid for a specific domain/subdomain - you should establish connection to your WebSocket server over the same address.
For example, cookies that only valid for admin.example.com won't be sent to a WebSocket server on your root domain (example.com).
2.In case your cookies only valid for a secure connection (https://), your WebSocket server should be over a secure connection too (wss://), Which is quite easy to achieve with the latest Ratchet version.
$webSock = new React\Socket\Server('0.0.0.0:8443', $loop);
$webSock = new React\Socket\SecureServer($webSock, $loop, [
'local_cert' => 'path_to_server_cert',
'local_pk' => 'path_to_private_key',
//'allow_self_signed' => TRUE,
'verify_peer' => FALSE
]);
3.With Ratchet 0.4.x, there is no longer a cookie parser.
You can only get it as a raw string and then parse it by yourself.
Get & Parse cookies with Ratchet 0.4.x :
$cookiesRaw = $conn->httpRequest->getHeader('Cookie');
if(count($cookiesRaw)) {
$cookiesArr = \GuzzleHttp\Psr7\parse_header($cookiesRaw)[0]; // Array of cookies
}
Related
If I start a session like below for a server and a localhost client try to request the server via HTTP, does it response with the session cookie?
or must it go through HTTPS?
I read the doc and it did say only through HTTPS, but I wonder if localhost is an exception.
session_start([
'cookie_secure' => true
]);
Yes, it does:
If you try this in a browser, you'll also see a warning saying that the cookie was rejected.
This makes sense because PHP has no control on the entire communication channel and it's possible that the end-user is connecting to a secure proxy that redirects internally to a non-encrypted HTTP server.
So, I am running a Ratchet (php) websocket server with multiple routes that connect do multiple Ratchet apps (MessageComponentInterfaces):
//loop
$loop = \React\EventLoop\Factory::create();
//websocket app
$app = new Ratchet\App('ws://www.websocketserver.com', 8080, '0.0.0.0', $loop);
/*
* load routes
*/
$routeOne = '/example/route';
$routeOneApp = new RouteOneApp();
$app->route($routeOne, $routeOneApp, array('*'));
$routeTwo = '/another/route';
$routeTwoApp = new AnotherApp();
$app->route($routeTwo, $routeTwoApp, array('*'));
From here I am binding a ZMQ socket, in order to be able to receive messages sent from php scripts run on the normal apache server.
// Listen for the web server to make a ZeroMQ push after an ajax request
$context = new \React\ZMQ\Context($loop);
$pull = $context->getSocket(\ZMQ::SOCKET_PULL);
$pull->bind('tcp://127.0.0.1:5050'); // Binding to 127.0.0.1 means the only client that can connect is itself
$pull->on('message', array($routeOneApp, 'onServerMessage'));
Finally, the server is started:
//run
$loop->run();
This works perfectly fine as long as i am binding only one of the ratchet apps to the ZMQ socket. However, i would like to be able to separately push messages to both of the Ratchet apps. For this purpose i thought of binding two ZMQ sockets to different routes like:
$pullOne->bind('tcp://127.0.0.1:5050' . $routeOne); // Binding to 127.0.0.1 means the only client that can connect is itself
$pullOne->on('message', array($routeOneApp, 'onServerMessage'));
and
$pullTwo->bind('tcp://127.0.0.1:5050' . $routeTwo); // Binding to 127.0.0.1 means the only client that can connect is itself
$pullTwo->on('message', array($routeTwoApp, 'onServerMessage'));
However, this leads to an error message from ZMQ when binding the second socket, saying the given address is already in use.
So the question is, is there any other way to use routes over a ZMQ socket?
Or should i use other means to distinguish between messages for the separate Ratchet apps, and if so, what would be a good solution?
I thought about binding to 2 different ports, but figured that would be a pretty ugly solution?!
In general in TCP packets are identified by the 4 tuple (sender ip, sender port, receiver ip, receiver port).
When a incoming packet reaches the network layer, it is forwarded to the appropriate application by looking at the receiver ip and port. If you use the same pair for both the apps, it will be impossible for the layer to decide whom to send it to when a connection comes in.
One solution would be to bind a single connection and the write a common handler that looks at the incoming content and then decides (I assume you have some logic) to differentiate the incoming connections to the different instances and then invokes the corresponding handler. The handler can get the connection object and can handle the connection hence forth.
If both your instances are identical and it doesn't matter who gets the request then you can just randomly forward the new connection to any of the handler.
Edit: I have tried to answer the question irrespective of the application type (Racket/ZMQ etc) because the issue you are trying to address is a fundamental one common to any network application.
For this case since you have two apps running and want to listen on the same port, you can have a common handler which can look at the request URL and forward the connection to the appropriate handler.
The request URL can be obtained using
$querystring = $conn->WebSocket->request->getQuery();
Now the clients can connect using
ws://localhost:5050/app1
and
ws://localhost:5050/app2
Your different apps can now handle these connections separately.
I am trying to set a simple client-server system for a mobile app.
Server side is written in PHP.
This server should handle requests from the app (a client) such as exchanging data in the form of json objects.
So i need my server to listen to requests and respond.
All the examples i found include the 'Socket' functions (socket_create(), socket_bind() etc.), and somewhere i need to specify the port i'm listening on.
My question is - the app sends the request to some url - http://example.com (or something like that).
Obviously in the client code i am not specifying the port i am sending the request to, so do i need to listen on all ports? How can i achieve this?
Usually PHP is used in combination with a web server (for example Apache or nginx), which handles the low-level socket communication, so that you can concentrate only on the business logic of your system.
This way, your server code can be as simple as:
<?php
echo json_encode(array(
'status' => 'OK',
'user' => array(
'id' => 6,
'username' => 'foo',
),
));
FYI: Web servers by default use port 80 for the http protocol and port 443 for https. So, when the port number is not specified, then the default values are used. For example http://example.com is the same as http://example.com:80.
I have a simple php file which makes SOAP requests. This is running on my local computer with XAMPP as a webserver.
I am trying to catch the request made in fiddler, I can see the request to my php file but that just returns the html for the page. I want to catch the request made when I create the SOAP client to see what is being sent off.
Is there some setting in fiddler I need to change to be able to see the response? Or some sort of proxy I can send my request through so it is visible in fiddler?
You can pass the proxy settings to the SoapClient class like this:
$client = new SoapClient("request.wsdl", array('proxy_host' => "localhost",
'proxy_port' => 8888));
This assumes that fiddler is running on it's default port (8888).
i've been trying to set up a secure communication using client side certificate between my client application and my server application.
I've set up a the configuration in my apache web server and both in my browser just to make sure that it works and it does.
i'm using zend framework 1.12, and according to the documentation on Zend website
the following example should work:
$config = array( 'sslcert' => 'path/to/ca.crt', 'sslpassphrase' => 'p4ssw0rd');
$adapter = new Zend_Http_Adapter_Socket();
$adapter->setConfig($config);
$http_client = new Zend_Http_Client();
$http_client->setAdapter($adapter);
$http_client->setUri('https://somewhere.overtherainbow.com:1337/bluebird');
$http_client->request();
but everytime i just get the same exception
Unable to Connect to ssl://somewhere.overtherainbow.com:1337
There is no doubt that i'm using the right certificate and passphrase and there is access to the remote machine
so where could be the downfall ?
Sounds like a simple firewall issue - login to the server and stop iptables and then see if it connects. Or add an exception to the clients IP to access mysql. Also check :1337 is open