几天前,我在网站的身份验证系统中实现了 cookie 功能,基本上身份验证系统使用会话和 cookie 来检查身份验证。一切正常,但今天我发现了一个奇怪的问题。那是在我关闭并重新打开浏览器之后,cookie仍在浏览器中,但我没有经过身份验证。到目前为止,我只有三个页面 index.php 在根文件夹中,然后是分类目录中的分类.php(分类/index.php),然后是用户目录中的 login.php(用户/登录.php) ..所以发生的事情是,在我重新启动浏览器并浏览 index.php 后,我没有通过身份验证,分类.php 也是如此,但 login.php 对我进行了身份验证。奇怪的是它都使用相同的代码..
这是 header.php(包含在所有三个文件中)
<?php
//header.php
// if cookie is set, authenticate directly
if (isset($_COOKIE['AUTH'])) {
include_once("../includes/initialize.php"); // requires and initializes all the necessary functions and classes
// cookie is set, lets see if its vailed and log someone in
global $database;
global $salt;
$now = time();
list($identifier, $token) = explode(':', $_COOKIE['AUTH']);
if (ctype_alnum($identifier) && ctype_alnum($token)) {
$user = User::find_by_identifier($identifier);
if ($token != $user->token) {
setcookie ("AUTH", "", time() - 3600);
session_destroy();
// echo "wrong token";
// fail because the key doesn't match
} elseif ($now > $user->timeout) {
setcookie ("AUTH", "", time() - 3600);
session_destroy();
// echo "timeout";
// fail because the cookie has expired
} elseif ($identifier!= md5($salt.md5($user->id.$salt))) {
// fail because the identifiers does not match
setcookie ("AUTH", "", time() - 3600);
session_destroy();
// echo "wrong identifier";
} else {
/* Success */
// $found_user = User::cookie_authenticate($user->email, $user->passwor,$ip);
$session->cookie_login($user);
}
} else {
/* failed because the information is not in the correct format in the cookie */
setcookie ("AUTH", "", time() - 3600);
session_destroy();
}
}
?>
index.php
<?php
//index.php
include_once("includes/initialize.php"); // requires and initializes all the necessary functions and classes
include_template("header.php");
?>
users/login.php
<?php
//login.php
include("../includes/initialize.php"); // requires and initializes all the necessary functions and classes
//if aready logged in
if($session->is_logged_in()) {
$session->message("<script> TINY.box.show({html:'You are already logged in!',animate:false,close:false,mask:false,boxid:'error',autohide:3,top:-14,left:-17})</script>");
redirect_to("../index.php");
}
include_template("header.php");
?>
我在 index.php 中注意到的是,即使浏览器保存了 AUTH cookie
if(isset($_COOKIE['auth']))
header.php 中的 isset 函数并没有真正检查 cookie 是否在 index.php 中设置,但是 login.php 确实.. 好吧,我不想发布更多代码,因为我知道问题不在于登录类或 cookie 类.. 因为我说,login.php 确实验证了 cookie .. 第一个问题是为什么 index.php 没有真正通过 isset($_COOKIE['AUTH'])) 函数,尽管在浏览器中设置了 cookie AUTH?
第二个是,为什么 login.php 传递相同的 isset cookie 函数,即使两者都包含编写 isset 函数的相同 header.php 文件。
我希望我把问题说清楚了,我尽我所能..对不起,我问这个问题的能力很差..
public static function authenticate($username="", $password="",$ip) { //login function to authenticate user
global $database;
$username = $database->escape_value($username);
$password = $database->escape_value(sha1($password));
$ip = $_SERVER['REMOTE_ADDR'];
$identifier = md5( $salt . md5($username . $salt ) );
$query = $database->query("SELECT id FROM ".static::$table_name." WHERE ip = '$ip' AND banned = '1'");
if ($database->num_rows($query) >= 1 ) { //change to 1
echo "<div class=\"warning\"> Your IP has been blocked, Possible Spam attempts. Please contact the Admin for further details.</div>";
} else {
$sql = "SELECT * FROM ".static::$table_name." ";
$sql .= "WHERE email = '{$username}' ";
$sql .= "AND password = '{$password}' ";
// $sql .= "AND active = '1' ";
$sql .= "LIMIT 1";
$result_array = self::find_by_sql($sql);
return !empty($result_array) ? array_shift($result_array) : false;
}
}
public function login($user) {
// database should find user based on username/password
if($user){
User::set_login_time($user->id); // set logged in time and identifier
User::set_cookie_details($user->id); // set cookie expiration time and token
$this->user_id = $_SESSION['user_id'] = $user->id;
$this->username = $_SESSION['username'] = $user->username;
$this->user_level = $_SESSION['user_level'] = $user->level;
$this->banned = $_SESSION['user_banned'] ;
$this->logged_in = true;
}
}
public function is_logged_in() {
return $this->logged_in;
}
public function cookie_login($user) {
// if cookie is set, check and match the cookies identifier and token with the stored identifier and token in the database
// if it matches then login without credentials
$this->user_id = $_SESSION['user_id'] = $user->id;
$this->username = $_SESSION['username'] = $user->username;
$this->user_level = $_SESSION['user_level'] = $user->level;
$this->banned = $_SESSION['user_banned'] ;
$this->logged_in = true;
}
public static function set_login_time($user_id) {
global $database;
global $salt;
$identifier = md5( $salt . md5($user_id . $salt ));
$time = time();
$sql = "UPDATE ".static::$table_name." SET modified = '$time',identifier = '$identifier' WHERE id = '{$user_id}' LIMIT 1 ";
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
}
public static function set_cookie_details($user_id) {
global $database;
$user = self::find_by_id($user_id);
$identifier = $user->identifier;
$key = md5(uniqid(rand(), true));
$timeout = time() + 60 * 60 * 24 * 7; // 1 week
setcookie('AUTH', "$identifier:$key", $timeout);
$sql = "UPDATE ".static::$table_name." SET token = '$key', timeout = '$timeout' WHERE id = '{$user_id}' LIMIT 1 ";
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
}
$user = User::authenticate($username, $password,$ip); // if returned true
$session->login($user);