First off, I will assume that you are rather new to PHP, and that is for a very specific reason: $_SESSION
is meant to be a server-side storage, and should not go to the client, at any time. Because you may store sensible data in a session, which you do not want to transmit over the network, especially since you dont want any unprevileged person to sniff the data and eventually leave yourself wide open for an RCE (Remote Code Execution) or SQL Injection attack.
When you look at individual values however, that is a little bit of a different story. A User ID can be used - but what if I ran a generator attack against this page with a range of 0 to 100 with each and every of those numbers being used as an ID? You need to consider this at any given time. It is very important.
Now - to actually answer your question.
First, there are two approaches you can take: Actually and really turning over the User ID, as long as you are sure that this ID can not be used for malicious attempts OR you can use Cookies with encrypted values - or, encrypt the cookies in general.
For option one, you'd do this:
var user_id = <?=json_encode($_SESSION["user_id"])?>;
This will encode your user_id
into JSON (JavaScript Object Notation) - which essentially is valid JavaScript, per-se. Therefore, if $_SESSION["user_id"]
happens to be an integer like 1
, the result would look like this:
var user_id = 1;
The second option of using encrypted cookies is a little bit, if not much trickier but also much more secure. Consider this:
<?php $salt = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher)); $cipher = "AES-128-CTR"; function encryptValue($value) { $secret = "..."; // See below $encryptedValue = openssl_encrypt($value, $cipher, $secret, 0, $salt) . "::" . bin2hex($salt); return $encryptedValue; } function decryptValue($value) { list($encryptedValue, $salt) = explode("::", $value); return openssl_decrypt($encryptedValue, $cipher, $secret, 0, hex2bin($salt)); }?>
(Resource: https://www.the-art-of-web.com/php/two-way-encryption/ )
Now, this is a very, very simplified encrypt/decrypt mechanism based on the OpenSSL extension and it will essentially encrypt values for you - and decrypt them. The important part is the $secret
. This is your encryption "password" that is being used to obfuscate what the user gets to see. Because basically, avoiding attacks starts by making it impossible to decipher what the values being sent to the server actually mean. In a production environment, at least. In development, you may actually leave this as clear-text - but that is a different topic.
So, now with those two functions available, you can do this:
<?php $value = null; if(array_key_exists("user_id", $_COOKIE)) { // The user has previously been assigned a `user_id`. $value = decrypt($_COOKIE["user_id"]); } else { // The user is possibly visiting for the first time, so they have no ID. $value = get_user_id_from_somewhere(); }?>
Now you will have a $value
containing either a fresh ID or one that had been sent beforehand.
But now you need to send this value to the client so it can be used in a XHR request. Well, you will need to set the cookie first. Once done so, you can take the example from the first option and do this:
var token = <?=json_encode(encrypt($_COOKIE["user_id"]))?>;
And with "something" I really mean it - the way you get to your encrypted token is up to you :)
Next, you may want to use it to send a XHR request, so you will need to encode it for a URL. You can even use this right away and save the token
variable alltogether with something like:
var url = "http://example.com/other.php?token=<?=urlencode(encrypt($_COOKIE["user_id"]))?>";
To access that URL parameter, use $_GET["token"]
in other.php
and decrypt it with the function from above (or with any other you come up with, really).
So which option should you choose in which case?- If you transfer data to your client which you are very sure can not be exploited and is safe for them to know about, use json_encode
and the raw variable from $_SESSION
. Keep in mind, that session variables are meant to be private to the server. In fact - PHP will actually send a PHPSESSION
cookie to the client, which uses such a hashed, almost encrypted-looking string, in order to identify the visitor on subsequent requests.- If you transfer data which you definitively do not want the client to see or even know about, encrypt it. The fewer the client knows about your business logic (contents of your scripts), the lower are the chances for an attack.
Also: Never trust a user, ever. This is very much an unwritten and yet golden rule. If you are not sure, then go with the most secure method you have at hand. Only if you are very, very sure, send values in a raw format to them - which they will be able to read in all their plain glory.
A little side-note to json_encode
: You can also encode an entire array as well: json_encode(["foo"=>"baz"])
will become: {"foo":"baz"}
, which is valid JSON, and JavaScript too.
Thus, one more side-note: If you haven't already, use PHP's official manual and start embracing Composer. You can find many, many useful tools there which can make your live as a PHP dev much easier.
I know this is a long answer, but I only mean well =) Good luck with your app!