php登录系统记住我的风格

时间:2013-01-24 18:07:00

标签: php remember-me login-script

我写了这段代码以安全方式启动会话

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 [“life”]增加到1个月吗?如果没有我应该如何实现1个月?我使用ssl然后我认为我的饼干是安全的。

更新

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

      <?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?

2 个答案:

答案 0 :(得分:2)

您需要使用cookies ...

现在我们需要让这个复选框做一些事情。也就是说,选中后,请记住用户的用户名,并将其放置在每个相应的登录页面访问的用户名字段中。为此,我决定使用cookies。我无法使用上面设置的“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设置为过去的时间,基本上将其杀死。

了解更多here ...

答案 1 :(得分:2)

详细了解其工作方式将花费更多时间来完成所有工作。但我应该能够为您提供有关其工作原理的高级摘要。

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

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

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

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

更改用户数据(如电子邮件/密码)应该要求用户输入密码。

网站应该使用SSL来使cookie拦截变得更加困难。