FIX Session::$cookie_secure so Sessions still work via HTTP

Session::$cookie_secure adds the secure property to the session Set-Cookie
command, so that the browser wouldnt send it to the server over an unencrypted
link. However the server would still send the cookie to the browser
unencrypted. Also Sessions would stop working properly in HTTP,
but SilverStripe needs them for several things, such as form validation

This patch effectively causes HTTP and HTTPS requests to each have
their own session when cookie_secure is true. The two sessions are
independant from each other, so information set in the session via
HTTPS is safe from attacks on the session via HTTP, but parts
of the site that use HTTP and the session will still work
This commit is contained in:
Hamish Friedlander 2013-07-06 15:10:43 +12:00
parent 2886f6ee14
commit d629d9422f
2 changed files with 16 additions and 3 deletions

View File

@ -127,7 +127,7 @@ class Director implements TemplateGlobalProvider {
}
// Only resume a session if its not started already, and a session identifier exists
if(!isset($_SESSION) && (isset($_COOKIE[session_name()]) || isset($_REQUEST[session_name()]))) {
if(!isset($_SESSION) && Session::request_contains_session_id()) {
Session::start();
}
// Initiate an empty session - doesn't initialize an actual PHP session until saved (see belwo)

View File

@ -513,6 +513,16 @@ class Session {
Session::set("FormInfo.$formname.formError.type", $type);
}
/**
* Is there a session ID in the request?
* @return bool
*/
public static function request_contains_session_id() {
$secure = Director::is_https() && Config::inst()->get('Session', 'cookie_secure');
$name = $secure ? 'SECSESSID' : session_name();
return isset($_COOKIE[$name]) || isset($_REQUEST[$name]);
}
/**
* Initialize session.
*
@ -522,7 +532,7 @@ class Session {
$path = Config::inst()->get('Session', 'cookie_path');
if(!$path) $path = Director::baseURL();
$domain = Config::inst()->get('Session', 'cookie_domain');
$secure = Config::inst()->get('Session', 'cookie_secure');
$secure = Director::is_https() && Config::inst()->get('Session', 'cookie_secure');
$session_path = Config::inst()->get('Session', 'session_store_path');
$timeout = Config::inst()->get('Session', 'timeout');
@ -538,11 +548,14 @@ class Session {
// Allow storing the session in a non standard location
if($session_path) session_save_path($session_path);
// If we want a secure cookie for HTTPS, use a seperate session name. This lets us have a
// seperate (less secure) session for non-HTTPS requests
if($secure) session_name('SECSESSID');
// @ is to supress win32 warnings/notices when session wasn't cleaned up properly
// There's nothing we can do about this, because it's an operating system function!
if($sid) session_id($sid);
@session_start();
}
// Modify the timeout behaviour so it's the *inactive* time before the session expires.