Lately, I've been getting the following error(s) in my log:
PHP Warning: session_start(): The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in [...] on line [..]
PHP Warning: Unknown: The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in Unknown on line 0
PHP Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/var/lib/php5) in Unknown on line 0
The answers to this previous question suffice for detecting and diverting such scenarios, so that no error is generated, but I'm interested in the most elegant recovery; that is, ending up with a valid new (empty) session.
First, though, a few refinements to the detection & diversion code in that previous question, which is now six years old:
These days, sessions are more likely to be handled exclusively through cookies. The
session.use_only_cookies
flag in my php.ini is enabled, and since I don't remember changing it I assume this is the default value.Which characters are used in a valid session id, and how many of those characters, depends on the
session.hash_function
andsession.hash_bits_per_character
values in php.ini. My values are 0 and 5, respectively, which (unless I'm mistaken) means my own session ids should match the regular expression/^[a-v0-9]{26}$/
. I assume these are default values as well.The name of the cookie used to store the session can be customized using
session.name
in php.ini. The correct value can always be retrieved using thesession_name()
function.
Given these, the most elegant means of diversion would (probably) be as follows:
function my_session_start() {
if (!isset($_COOKIE[session_name()]) || preg_match('/^[a-v0-9]{26}$/', $_COOKIE[session_name()]) !== 0) {
return session_start(); // since 5.3, returns TRUE on success, FALSE on failure.
}
else {
return false;
}
}
As for recovery (which would replace the return false;
in the else
block), one answer to the previous question suggested the following:
session_id(uniqid());
session_start();
session_regenerate_id();
I'm concerned, however, that this means of recovery, having received only two upvotes and no comments, is insufficiently reviewed.
The answer to this question suggests that the internal session_start()
function relies directly on the value of $_COOKIE[session_name()]
, rather than some other internal representation of that value. Is this the case? If so, a my_session_start()
function with detection and recovery could be as simple as:
function my_session_start() {
if (isset($_COOKIE[session_name()]) && preg_match('/^[a-v0-9]{26}$/', $_COOKIE[session_name()]) === 0) {
unset($_COOKIE[session_name()]);
}
return session_start();
}