使用唯一令牌保护登录

时间:2012-02-08 18:02:06

标签: php security authentication

我的用户授权过程就是这样。

在登录过程中,函数会触发代码。

 $token = sha1(microtime(true) . mt_rand(10000, 90000));
 setcookie('auth', $token, $timeout);

然后在用户id列之后立即将生成的token添加到数据库表中。 BTW,$_SESSION$_COOKIE只存储$token值。

另一个名为protect的函数位于每个页面的顶部,并检查是否存在cookie:

  1. 首先检查db表中的$token:如果没有这个用户 令牌,签出
  2. 然后使用存储在db表中的那些检查$_SERVER['HTTP_USER_AGENT']$_SERVER['REMOTE_ADDR']
  3. 问题

    我觉得这不是安全的方式,因为如果攻击者使用相同的PC和相同的浏览器,只需通过“复制粘贴”cookie即可访问。另外$ _SERVER ['REMOTE_ADDR']并不总是有效。

    如何使此登录更安全?

    详细

    这是功能保护

    public function protect() {
        if (!isset($_SESSION)) {
            session_start();
        }
        $data = array();
    
        if (isset($_SESSION['auth'])) {
            $stmt = $this->db->prepare("SELECT l.browser, l.ip, u.ban from log AS l, users AS u WHERE l.token =? AND u.id=l.user_id LIMIT 1") or die($this->db->error);
            $stmt->bind_param("i", $_SESSION['auth']) or die($stmt->error);
            $stmt->execute() or die($stmt->error);
            $stmt->store_result();
            if ($stmt->num_rows == 0) {
                $this->signout();
            }
            $stmt->bind_result($data['browser'], $data['ip'], $data['ban']);
            $stmt->fetch() or die($stmt->error);
            $stmt->close() or die($stmt->error);
            $this->validation->check("protection", $data);
        } else {
            if (!isset($_COOKIE['auth'])) {
                header('Location:' . wsurl);
            }
            $stmt = $this->db->prepare("SELECT l.browser, l.timeout, l.ip, u.ban from log AS l, users AS u where l.token =? AND u.id=l.user_id LIMIT 1") or die($this->db->error);
            $stmt->bind_param("s", $_COOKIE['auth']) or die($stmt->error);
            $stmt->execute() or die($stmt->error);
            $stmt->store_result();
            if ($stmt->num_rows == 0) {
                $this->signout();
            }
            $stmt->bind_result($data['browser'], $data['timeout'], $data['ip'], $data['ban']) or die($stmt->error);
            $stmt->fetch() or die($stmt->error);
            $this->validation->check("protection", $data);
            session_regenerate_id();
            $_SESSION['auth'] = $_COOKIE['auth'];
            $stmt->close() or die($stmt->error);
        }
    }
    

    验证检查此

    if ($data['browser'] != md5($_SERVER['HTTP_USER_AGENT'])) {
                $this->registration->signout();
            }
    
            if ($data['ban'] == 1) {
                $this->registration->signout(false);
                header('Location:' . wsurl . "?page=msg&id=34");
            }
            if ($data['ip'] != $this->common->getIP("long")) {
                $this->registration->signout();
            }
    
            if (isset($data['timeout']) && !empty($data['timeout'])) {
                if (($data['timeout'] - $this->common->getTime()) < 0) {
                    $this->registration->signout();
                }
            }
    

2 个答案:

答案 0 :(得分:4)

在不影响应用程序可用性的情况下,您无能为力。例如,您可以使用用户IP,用户代理或用户提供的环境变量的混合作为令牌的盐,但如果用户IP已更改或任何环境变量(不一定是静态的),则不会再次登录。

老实说,这不是您应该担心的安全问题,这是用户的责任。如果有人可以使用他们的计算机并复制他们的cookie,他们可能会采取额外的步骤直接提取他们的密码(如果他们使用Firefox,则很容易..)。

答案 1 :(得分:1)

我可能误解了 - 但是可以窃取cookie的攻击者可以通过创建cookie并将HTTP_USER_AGENT, REMOTE_ADDR元素添加到被盗令牌来窃取会话。

我会设置令牌,并拥有一个带

的数据库表
TOKEN    REMOTE_ADDR  HTTP_USER_AGENT
------------------------------------

列。您的protect()方法应检查令牌,然后将当前用户的远程地址和用户代理与数据库进行比较。

这样,可以窃取你的cookie的攻击者也必须能够模仿你的浏览器(琐碎的)和IP地址(更难,但仍然可以)。

另外,请检查this question