-1

我写了这段代码以安全的方式开始会话

function sessionStart() {
    $session_name = 'sec_session_id'; // Set a custom session name
    $secure = false; // Set to true if using https.
    $httponly = true; // This stops javascript being able to access the session id. 

    ini_set('session.use_only_cookies', 1); // Forces sessions to only use cookies. 
    $cookieParams = session_get_cookie_params(); // Gets current cookies params.
    session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $secure, $httponly); 
    session_name($session_name); // Sets the session name to the one set above.
    session_start(); // Start the php session
    session_regenerate_id(true); // regenerated the session, delete the old one. 
}

现在我有一个问题,如果我们有这个 session_regenrate_id 那么我们的会话 ID 将在每个页面中执行时发生变化?如果我为会话重新生成 ID,我应该如何为想要登录 1 个月的用户使用 cookie?例如,将 $cookieParams["lifetime"] 增加到 1 个月是否安全?如果没有,我应该如何在 1 个月内实现这一目标?我使用 ssl,然后我认为我的 cookie 是安全的。

更新

我去的另一种方法是将会话存储在数据库中。

      <?php
    /**
     * PDO Session Handler
     * @author Daniel15 <dan.cx>
     *
     * This class is actually static, but since PHP doesn't support static classes, abstract is close
     * enough. You do not instantiate the class; you just call the static "init" method.
     */
    abstract class PDOSession
    {
            private static $db;
            private static $oldData;
            /**
             * Initialise the PDO session handler
             * @param PDO PDO instance to use for database
             */
            public static function init(PDO $db)
            {
                    self::$db = $db;
                    // Add the session handlers
                    session_set_save_handler('PDOSession::open', 'PDOSession::close', 
                                             'PDOSession::read', 'PDOSession::write', 
                                             'PDOSession::destroy', 'PDOSession::garbageCollect');
                    session_start();
            }

            /**
             * Session open handler
             * @param string Path to save session to
             * @param string Name of the session
             */
            public static function open($save_path, $session_name)
            {
                    // Nothing
                    return true;
            }

            /**
             * Session close handler
             */
            public static function close()
            {
                    // Nothing
                    return true;
            }

            /**
             * Session load handler. Load the session
             * @param string Session ID
             */
            public static function read($session_id)
            {
                    // Load the session data from the database
                    $query = self::$db->prepare('
                            SELECT data
                            FROM sessions
                            WHERE session_id = :session_id');
                    $query->execute(array(':session_id' => $session_id));

                    return $query->fetchColumn();
            }

            /**
             * Session save handler. Save the session
             * @param string Session ID
             * @param string Data to save to session
             */
            public static function write($session_id, $data)
            {
                    /* Try to update the existing session. If we can't find one, then create a new one. If you
                     * are using MySQL, this can be done in a single INSERT statment via INSERT ... ON 
                     * DUPLICATE KEY UPDATE. Remove the UPDATE and edit the INSERT to do it this way.
                     * See http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
                     *
                     * This does two queries so you can use any DBMS.
                     */

                    $query = self::$db->prepare('
                            UPDATE sessions
                            SET data = :data, last_activity = :last_activity
                            WHERE session_id = :session_id');
                    $query->execute(array(
                            ':session_id' => $session_id,
                            ':data' => $data,
                            'last_activity' => time()));

                    // No session to update? Create a new one
                    if ($query->rowCount() == 0)
                    {
                            self::$db
                                    ->prepare('
                                            INSERT INTO sessions
                                                    (session_id, data, last_activity)
                                            VALUES
                                                    (:session_id, :data, :last_activity)')
                                    ->execute(array(
                                            ':session_id' => $session_id,
                                            ':data' => $data,
                                            'last_activity' => time())
                                    );
                    }
            }

            /**
             * Session delete handler. Delete the session from the database
             * @param string Session ID
             */
            public static function destroy($session_id)
            {
                    self::$db
                            ->prepare('
                                    DELETE FROM sessions
                                    WHERE session_id = :session_id')
                            ->execute(array(':session_id' => $session_id));
            }

            /**
             * Session garbage collector. Delete any old expired sessions
             * @param int How many seconds do sessions last for?
             */
            public static function garbageCollect($lifetime)
            {               
                    self::$db
                            ->prepare('
                                    DELETE FROM sessions
                                    WHERE last_activity < :min_time')
                            ->execute(array(':min_time' => time() - $lifetime));
            }
    }
?>

现在为此我应该如何在这种情况下创建cookie?

4

2 回答 2

2

你需要使用cookies...

现在我们需要让这个复选框做一些事情。即,选中时,记住用户的用户名,并将其放在用户每次相应访问登录页面时的用户名字段中。为此,我决定使用 cookie。我无法使用我在上面设置的“ID_my_site”用户名 cookie,因为每次用户注销时它都会被杀死。解决方案是创建一个名为“remember”的附加 cookie,它也存储用户名,如下所示:

$year = time() + 31536000;
setcookie('remember_me', $_POST['username'], $year);

上面我们添加了这个额外的cookie,持续一年,这样当用户登录时,它会创建一个额外的cookie来保存用户的用户名。但是,目前,它没有被使用。改变:

<input type="text" name="username" maxlength="40">

至:

<input type="text" name="username" maxlength="40" value="<?php
echo $_COOKIE['remember_me']; ?>">

在我们的登录表单中,现在将此用户名存储到文本字段中以供将来访问:

不过,我们还没有完成。目前,代码正在为每个用户存储这些信息。我们希望它只记住那些特别请求此功能的用户。为此,我们在创建附加 cookie 之前运行一个简单的检查。此检查查看是否已选中记住我复选框,如果已选中,则仅创建我们的新 cookie。像这样:

if($_POST['remember']) {
setcookie('remember_me', $_POST['username'], $year);
}
elseif(!$_POST['remember']) {
    if(isset($_COOKIE['remember_me'])) {
        $past = time() - 100;
        setcookie(remember_me, gone, $past);
    }
}

上面的代码还处理了存在 cookie 的情况,但用户通过将任何现有的 cookie 设置为过去的时间来确定他们不再希望被记住,实际上是杀死它们。

在这里阅读更多...

于 2013-01-24T18:17:16.740 回答
2

详细了解它的工作原理将花费比我全部写完更多的时间。但我应该能够为您提供有关其工作原理的高级摘要。

PHP 会话是有时间限制的。他们会在一段时间后被清理干净。您可以在 PHP 配置中延长该时间,但不足以有效。

所以需要做的是创建一个替代的登录路径。这必须谨慎实施,因为不小心会打开安全漏洞。

该概念可以概括为创建与用户相关联的一次性使用的唯一 cookie,并可用作用户名和密码的替代品。

此 cookie 应该是唯一的,由随机数据生成,并与用户关联存储。它应该是有时间限制的(如果在一两周内不使用它将过期)并在使用后重新生成。

更改电子邮件/密码等用户数据应需要用户密码。

站点应该使用 SSL 使 cookie 拦截更加困难。

于 2013-01-24T18:30:53.290 回答