Explorar o código

Update PDO session storage to check if any rows are updated when doing a session write. If no rows are udpated when performing a session write it generally means that we have created a new session id somewhere and we have not inserted into the database. This is the case for when calling regenerate_session_id() from the native session storage class. It will update the session id then call sessionWrite() to save the session but since the new session id does not exist in the DB, no rows are updated and any new session attributes such as security tokens are lost.

See http://www.php.net/manual/en/function.session-set-save-handler.php#103055 for more details
michaelwilliams %!s(int64=14) %!d(string=hai) anos
pai
achega
46b711c4a8

+ 33 - 7
src/Symfony/Component/HttpFoundation/SessionStorage/PdoSessionStorage.php

@@ -15,6 +15,7 @@ namespace Symfony\Component\HttpFoundation\SessionStorage;
  * PdoSessionStorage.
  *
  * @author Fabien Potencier <fabien@symfony.com>
+ * @author Michael Williams <michael.williams@funsational.com>
  */
 class PdoSessionStorage extends NativeSessionStorage
 {
@@ -174,13 +175,7 @@ class PdoSessionStorage extends NativeSessionStorage
             }
 
             // session does not exist, create it
-            $sql = 'INSERT INTO '.$dbTable.'('.$dbIdCol.', '.$dbDataCol.', '.$dbTimeCol.') VALUES (?, ?, ?)';
-
-            $stmt = $this->db->prepare($sql);
-            $stmt->bindParam(1, $id, \PDO::PARAM_STR);
-            $stmt->bindValue(2, '', \PDO::PARAM_STR);
-            $stmt->bindValue(3, time(), \PDO::PARAM_INT);
-            $stmt->execute();
+            $this->createNewSession($id);
 
             return '';
         } catch (\PDOException $e) {
@@ -213,10 +208,41 @@ class PdoSessionStorage extends NativeSessionStorage
             $stmt->bindParam(1, $data, \PDO::PARAM_STR);
             $stmt->bindParam(2, $id, \PDO::PARAM_STR);
             $stmt->execute();
+
+            if (!$stmt->rowCount()) {
+                // No session exists in the database to update. This happens when we have called
+                // session_regenerate_id()
+                $this->createNewSession($id, $data);
+            }
         } catch (\PDOException $e) {
             throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
         }
 
         return true;
     }
+
+    /**
+     * Creates a new session with the given $id and $data
+     *
+     * @param string $id
+     * @param string $data
+     */
+    private function createNewSession($id, $data = '')
+    {
+        // get table/column
+        $dbTable    = $this->options['db_table'];
+        $dbDataCol = $this->options['db_data_col'];
+        $dbIdCol   = $this->options['db_id_col'];
+        $dbTimeCol = $this->options['db_time_col'];
+
+        $sql = 'INSERT INTO '.$dbTable.'('.$dbIdCol.', '.$dbDataCol.', '.$dbTimeCol.') VALUES (?, ?, ?)';
+
+        $stmt = $this->db->prepare($sql);
+        $stmt->bindParam(1, $id, \PDO::PARAM_STR);
+        $stmt->bindValue(2, $data, \PDO::PARAM_STR);
+        $stmt->bindValue(3, time(), \PDO::PARAM_INT);
+        $stmt->execute();
+
+        return true;
+    }
 }