I've got a python/WSGI app which needs to check to see if a user has logged on to a PHP web app. The problem is that the PHP app checks if a user has logged on by comparing a value in the $_SESSION variable to a value in the cookie from the user's browser. I would prefer to avoid changing the behavior of the php app if at all possible.
My questions:
Is there anyway I can access the session variables from within python? Where should I start to look?
Are there any obvious security/performance issues I should be aware of when taking this approach?
yep. session (in default) is a regular file. so all what you need is look over session directory and find file with name of session cookie value. then - you have to implement php-like serialize/unserialize and do whatever you want.
nope
Depends on the PHP app, if it's keeping session data in a database (MySQL maybe) you can just connect to the database and get the data, if it's using native PHP sessions you should look to the session.save_path config setting in php.ini, that's the place where the runtime saves files with the session data.
Once you have the data you can parse it to get it unserialized, take a look at how serialize() and unserialize() work in PHP.
I'm currently in the process of trying to run a python server side by side with an existing Apache/php one. A custom solution I arrived at was to save the $_SESSION as an encrypted cookie, letting the php authentication operate as before, then share a private key between the two servers.
Two issues:
Up to you how to handle session expiry stuff.
I haven't bothered with an Initialization Vector, assuming the time stamp from my expiry stuff is enough. See https://stackoverflow.com/a/12486940/4495503 for why I might be being too security lax...
Anyway, my php encrypted cookie function:
session_start();
$encryptToCookie = function($varToEncode,$cookieName,$privateKey){
$iv = $privateKey;
$pass = $privateKey;
$method = 'aes-128-cbc';
$encryptedString = openssl_encrypt(json_encode($varToEncode), $method, $pass, true, $iv);
setcookie($cookieName,bin2hex($encryptedString));
};
$encryptToCookie($_SESSION,"sessionEncrypted","yohoyohoyohoyoho"); // private key must be 16bit
And my python side decryption:
from subprocess import Popen, PIPE
import binascii
def decrypt(encryptedString,privateKey):
encryptedString = binascii.unhexlify(encryptedString)
pathToOpenSSL = 'C:\pysrc\openssl\openssl.exe' # MODIFY THIS!!
openssl = Popen([pathToOpenSSL,
'enc','-aes-128-cbc','-d',
'-nosalt','-nopad','-K',
privateKey.encode('hex'),
'-iv',
privateKey.encode('hex')],
stdin=PIPE,stdout=PIPE)
decryptedString = openssl.communicate(encryptedString)[0].replace('\x04','')
return decryptedString
decrypt(encryptedString,'yohoyohoyohoyoho')
Hope this is of help to someone, remember all the usual stuff about generating private keys and then being careful with them!
Related
I'm currently coding one of my first php applications.
The application has to connect to a LDAP server and change some user attributes in the directory.
That application has some parameters to read in a mySQL Database in order to run.
Some examples of these parameters could be:
-LDAP Address
-LDAP Service Account
-LDAP Password
there are much more parameters, which rule, for example, the way users authenticate to my application,...
Currently, the database is read at each user session initialization, but, it doesn't have any sense because parameters do not vary from a session to another.
So, i'm looking for a way to load these parameters from the database, only one time (for example, at the php service initialization), and access to these parameters in the "normal" php code through variables.
What would be the best way to do this?
Thank you in advance.
You are looking for a persistent cross-request storage. There are many options for this.
The simplest is APCu (which can be used in conjunction with Zend OpCache, or for PHP < 5.5, APC).
Simply:
if (apc_exists('mykey')) {
$data = apc_fetch('mykey');
} else {
// create it from scratch
apc_store('mike', $data);
}
$data can be most any PHP type, arrays, objects, or scalars.
You can even put this code in the auto_prepend_file INI setting so it is run automatically on every request.
However: this is per server (and per SAPI, so mod_php/php-fpm/cli don't share the cache) so you will have to create it once per server.
Alternatively, for a multi-server setup you can use something like memcached or redis. These are stand-alone daemons that will let you store arbitrary key/value pairs of string data (so you may need to serialize()/unserialize() on the values).
I personally prefer memcache, which has two extensions for PHP, pecl/memcached and pecl/memcache (I prefer pecl/memcached, it has more features).
Both of them are pretty simple.
pecl/memcached:
$memcache = new Memcached();
$memcache->addServer('localhost', '11211');
$data = $memcache->get('mykey');
if (empty($data)) {
// Create data
$memcache->set('mykey', $data);
}
pecl/memcache:
$memcache = new Memcache();
$memcache->connect(); // uses localhost:11211, the default memcache host/port
$data = $memcache->get('mykey');
if (empty($data)) {
// Create data
$memcache->set('mykey', $data);
}
Both extensions support storage of arrays and objects without serialization.
You can of course store multiple keys with any of these solutions and just pull them all, instead of using one, or one with an array/object.
You can use Memcache do cache database requests. See here how to use.
Another way is using Php Sessions.
<?php
session_start(); // need to be before any html code
$_SESSION['something'] = 'Something here...';
echo $_SESSION['something']; // will show "Something here..."
And you can remove using...
unset($_SESSION['something']);
You also can use cookies, using the function setcookie. See here.
And you can get cookies using...
echo $_COOKIE['something'];
Production mode
In a production mode, this will work as set_transient of Wordpress. You will do the first db request to get the value and will cache this value using cookies, sessions or memcache.
If you want to show this values inside of your page, you can use a standard caching library.
My understanding of the question is that you have some SQL data that is more or less constant and you don't want to have to read that in from the SQL connection on every request.
If that is the case you can use memcache to store the data:
http://php.net/manual/en/book.memcache.php
The data will still be persistent and you will only need to go to the database if the cached data isn't there or needs to be refreshed.
If the data is specific to a particular user you can just use a session.
http://php.net/manual/en/book.session.php
http://php.net/manual/en/session.examples.basic.php
If this is only to be used when starting up your server (so once and done) and you don't want to bother to with memcached/xcache (as they would be over kill) you can still use environment variables. See get_env
I've not found any session handling with mod_lua.
So I guess I'll have to write my own session handler.
Note: that's great because Php lacks of handling timeouts by values, it only handles timeout for the whole session.
I'm just looking for the source code of Php where it generates the unique number of the session, to make it with mod_lua.
I've downloaded the whole Php code source but... I don't know where to look.
Why not just use r.log_id to get a unique number?
or something like:
local session_id = r:getcookie("lua_sessionid")
if not session_id then
session_id = r:sha1(r.log_id .. r.clock())
r:setcookie{
key = "lua_sessionid",
value = session_id
}
end
Alternately, see http://modlua.org/recipes/cookies for how to work with cookies and unique IDs.
The code for generating PHP session ids is in php_session_create_id, which is available for anyone to view at https://github.com/php/php-src/blob/0021095c40a2c2d3d95398c48ae83a06f1381f71/ext/session/session.c#L284
I set cookies like this:
$this->Cookie->write('mycookie', $data, TRUE, '30 days');
And I read them like this:
$cookieData = $this->Cookie->read('mycookie');
But for security concerns I read some of the cookies like this:
$cookieRaw= $_COOKIE['CakeCookie']['mycookie'];
And I write this raw cookie to my database. Then I need to read the content of the cookie.
But as you know raw cookie is something like "Q2FrZQ=dsdsaDASDasdasdsa".
So I need to read the content of the cookie.
It seems like CookieComponent:read() uses protected CookieComponent:_decrypt function. I don't want to copy paste the _decrypt() contents. Is there an easier way to read decrypted CakePHP strings ?
I don't see a reason for not using CookieComponent, for your information this component DO encrypt whatever you write. Here is an extract of the documentation
All values in the cookie are encrypted by default. If you want to store the values as plain-text, set the third parameter of the write() method to false. The encryption performed on cookie values is fairly uncomplicated encryption system. It uses Security.salt and a predefined Configure class var Security.cipherSeed to encrypt values. To make your cookies more secure you should change Security.cipherSeed in app/Config/core.php to ensure a better encryption.:
If you need to store the data encrypted, then I'd suggest to encrypt it yourself instead of relying on the cookie component internals.
ie, read the cookie data using the cookie component so that you end up with the decrypted data, then encrypt it with your favorite encryption algorithm (I'd suggest to use Security::rijndael()) and store it in the database, that way you have proper control over the data.
Another option would be to create a custom component that extends the cookie component and makes the decrypting functionality public. However I really don't think that's a good idea, the data in the DB shouldn't be a components concern, this is something that fits way better in the model layer.
If you insist using the mundged cookie data and decrypting it manually, then you'll have to do the same as can be seen in the CookieComponent code. First strip the Q2FrZQ==. from the data, then base64 decode it, afterwards decrypt it according to the method used by the cookie component (Security::cipher() by default, which is btw deprecated), and finally JSON decode it if necessary as in CookieComponent::_explode().
Assuming that only Cake 2.x style cookie data is used, and that the data is expected to be always encrypted, then it could be broken down to this (where the decryption method might need to be adjusted, depending on the cookie component configuration):
$data = substr($data, 8);
$data = base64_decode($data);
$data = Security::cipher($data, Configure::read('Security.salt'));
$first = substr($data, 0, 1);
if ($first === '{' || $first === '[') {
$decoded = json_decode($data, true);
if($decoded !== null) $data = $decoded;
}
However this heavily relies on the cookie component internals and configuration, so again, this is anything but recommended!
I have to read a file and do some computation, than save the result of this computation inside a variable.
I just need to do this once. In Java + Servlet I can do this using a servlet container and, for instance, the singleton pattern.
I know that in PHP I can't act like this. Which is the better way to do this? Save the computation (or transfer the data) on DB?
No, it won't work like with Java Servlets. You'll have to find a workaround.
First, I assume that using $_SESSION, $_COOKIE or $_REQUEST in general isn't practicable to you as you want to save the state per server (or per application) and not per 'User Session'.
Using a database sounds practicable in your case. In a regular application design it will be the most common solution.
Also you can do something like this, using the serialization capabilities of PHP:
<?php
$resultfile = 'result.dat';
if(!file_exists($resultfile)) {
$result = compute_result('foo bar');
file_put_contents($resultfile, serialize($result));
} else {
$result = unserialize(file_get_contents($resultfile));
}
Using PHP's serialize() attempt is especially practicable when
You are in a PHP only environment
$result is a complex datatype but you don't want to create a database structure and map $result too it
If you are not in a PHP only environment you might prefer other serialization formats as JSON or XML.
Also the serialization result can be stored as a string in a database instead of a file. Saving it to a database instead of a file would make the application more scalable as the result would be available to all servers that access the same database (cluster).
In short: I would suggest using a database maybe combined with serialization.
I need to call php script from main script that will run in background (i just want to call and proceed without waiting for response)
But I need access to user session in called script
My advice is don't use default PHP session because it might be tricky working with background process .... I would recommend session_set_save_handler http://www.php.net/manual/en/function.session-set-save-handler.php for a DB bases session
There is a good example here http://www.php.net/manual/en/function.session-set-save-handler.php#96305
Call
string file_get_contents ( string $filename [, bool $use_include_path = false [, resource $context [, int $offset = -1 [, int $maxlen ]]]] )
with $maxlen =0;
In filename you can give the url. In that url pass session id and in the called script set session id using session_id() and then call session_start().
Make sure that called script returns at least 520 dummy characters using flush() and ob_flush(), so that calling script do not wait.
The whole point behind a "session" is so that a user client can connect to the server multiple times in a "state-less" fashion, yet still maintain "state" like one single connection. "Session" data is shared between multiple connections from the same user client.
When you spawn off a background process on the server, whether or not you're using PHP, the "session" no longer has any real meaning. The user might even shut his client machine off with no effect on the server background process.
With that in mind, using Cookies as suggested elsewhere is totally useless. Cookies are saved on the client machine, and the background process will have Zero access to it.
If there is client information that your background process will need, then the calling process needs to pass it to the background process somehow, either as some kind of parameter or as some kind of a data file.
I would recommend saving the "$_SESSION" variable as a Json-encoded data string to a temporary file. The background process can read that file, Json-decode it back into an array, then use it just as if it were still a $_SESSION. Then remove the temporary file.
$_COOKIE['PHPSESSID'] = 'user_session_id';//Transfer parameters through $GLOBALS['argv']
session_start();