【问题标题】:Working with sessions and cookies in PHP在 PHP 中使用会话和 cookie
【发布时间】:2012-01-18 14:06:45
【问题描述】:

在登录期间,我使用以下函数来设置 cookie 和会话

protected function validateUser($userid, $ckey=0, $rememmber=0) {
    session_start();
    session_regenerate_id(true); //this is a security measure
    $_SESSION['user_id'] = $userid;
    $_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
    if (isset($remember) && $rememmber == 'on') {
        setcookie("user_id", $_SESSION['user_id'], time() + 60 * 60 * 24 * COOKIE_TIME_OUT, "/");
        setcookie("user_key", sha1($ckey), time() + 60 * 60 * 24 * COOKIE_TIME_OUT, "/");
    }
    return true;
}

然后在安全用户页面上,使用 user_id 检查user_id 以从数据库中获取有关用户的所有重要数据

public function protect() {
        session_start();

        /* Secure against Session Hijacking by checking user agent */
        if (isset($_SESSION['HTTP_USER_AGENT'])) {
            if ($_SESSION['HTTP_USER_AGENT'] != md5($_SERVER['HTTP_USER_AGENT'])) {
                $this->signout();
                exit;
            }
        }

// before we allow sessions, we need to check authentication key - ckey and ctime stored in database

        /* If session not set, check for cookies set by Remember me */
        if (!isset($_SESSION['user_id'])) {
            if (isset($_COOKIE['user_id']) && isset($_COOKIE['user_key'])) {
                /* we double check cookie expiry time against stored in database */

                $cookie_user_id = $_COOKIE['user_id'];
                               $stmt = $this->db->prepare("select `ckey`,`ctime` from `users` where `id` =?") or die($this->db->error);
            $stmt->bind_param("i", $cookie_user_id) or die(htmlspecialchars($stmt->error));
            $stmt->execute() or die(htmlspecialchars($stmt->error));
            $stmt->bind_result($ckey, $ctime) or die($stmt->error);
            $stmt->close() or die(htmlspecialchars($stmt->error));
                // coookie expiry
                if ((time() - $ctime) > 60 * 60 * 24 * COOKIE_TIME_OUT) {
                    $this->signout();
                }
                /* Security check with untrusted cookies - dont trust value stored in cookie.       
                  /* We also do authentication check of the `ckey` stored in cookie matches that stored in database during login */

                if (!empty($ckey) && is_numeric($_COOKIE['user_id']) && $_COOKIE['key'] == sha1($ckey)) {
                    session_regenerate_id(); //against session fixation attacks.

                    $_SESSION['user_id'] = $_COOKIE['user_id'];
                    $_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
                } else {
                    $this->signout();
                }
            } else {
                if ($page != 'main') {
                    header('Location:' . wsurl);
                    exit();
                }
            }
        }
    }

我想知道,出于安全目的,仅在 cokkies 和 session 中存储 user_id 和 user_agent 是否足够?如果没有,还有什么?

【问题讨论】:

  • 您可能希望在会话中添加令牌以防止 CSRF:shiflett.org/articles/cross-site-request-forgeries
  • 您应该从不将敏感数据(例如用户 ID)存储在 cookie 中,始终使用会话。
  • @animuson 那么,如何记住用户呢?
  • 这只是用户 ID。它不像密码或任何东西
  • @AuthmanApatira 是的,我同意你的看法。这只是一些数字。 animuson 请解释一下你的想法。

标签: php session cookies session-cookies


【解决方案1】:
$rs_ctime = $this->db->query("select `ckey`,`ctime` from `users` where `id` = -> '$cookie_user_id'<-")

似乎这里是 SQL 注入。如果您将 GET、POST、COOKIE 中的变量直接传递给 sql-query,这是注入的标志。

通常存储 user_id 和 user_agent 就足够了。但是一些支付服务有时会通过电话发送带有一些代码的短信并检查它来进行验证。但它通常用于非常安全的服务

【讨论】:

    【解决方案2】:

    会话存储在服务器上,您已经在登录后立即根据Wikipedia's Session Hacking Prevention 重新生成会话密钥,所以我想说您只存储用户代理和用户 ID 就很好。但是,我不会在每次安全页面查看后重新生成会话 ID(例如,从 validateUser() 函数中删除 session_regenerate_id())。 Wikipedia 建议只在登录时执行一次……除此之外的任何事情都是失控的。不过,我也会将 session_start() 从函数中移出,并在您的代码中处于较高位置。

    祝你编码好运!

    【讨论】:

    • protect() 位于每个用户页面的顶部。所以 session_start 将在顶部))
    猜你喜欢
    • 2014-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-26
    • 2012-02-01
    • 2013-07-03
    • 2015-11-30
    相关资源
    最近更新 更多