【发布时间】:2017-05-14 14:16:28
【问题描述】:
我正在开发 PHP 中的用户身份验证类,但在会话处理方面遇到了一些问题。
这是基础:
global.php我有一个名为global.php的文件,它包含在每个页面加载的开头。在这个文件中,我还包含了其他使用的类,例如我正在处理的class.uservalidation.php。 我在global.php文件中启动会话。class.uservalidation.php当此类在global.php文件的开头被实例化时,在构造函数中调用checkLogin方法来检查会话变量email和hash,如果它们匹配它会将auth属性设置为所选用户的级别。login.php是登录页面(显然...),提交时将调用 uservalidation 类的login方法。当登录成功时,此方法将设置两个会话变量email和hash。index.php是默认登陆页面,会根据登录状态显示不同的内容
这是它如何工作的一个例子:
我去login.php。会话开始,类加载一个实例化。 checkLoginmethod 将首先报告auth=0。我提交表单并再次加载相同的页面。 checkLogin 将首先报告 auth=0 在类被实例化时再次报告。然后在login.php 脚本中调用login 方法并设置会话变量。
但是……
当我执行print_r($_SESSION); 时,我只能从login.php 文件中看到会话变量,而不是从global.php 或class.uservalidation.php(即使这是我设置会话变量的位置)。
这是一个问题,因为我需要在后续页面加载时通过 loginCheck 方法检查 email 和 hash 会话变量。
由于$_SESSION 是一个超全局对象,我认为它可以从任何地方访问,但我不知道出了什么问题...
我觉得我在这里遗漏了一些非常基本的东西......我对 OOP 很陌生,所以可能是我遗漏了一些关于如何声明变量或其他东西的知识,但因为它是一个超全局的我认为没关系。
[编辑#1]
这是一些代码(由于某种原因,我无法粘贴到此文本框中,所以我创建了指向 pastebin 的链接):
global.php:
<?php
// Load configuration
require 'config.php';
// Start secure session
session_start();
// Include libraries
require 'class.uservalidation.php';
//Connect to database
// Initialize user validation
$USER=new Uservalidation();
?>
class.uservalidation.php
<?php
/*
--------------------------------------------------------------------------------------
class.uservalidation.php
--------------------------------------------------------------------------------------
Based on example at http://www.wikihow.com/Create-a-Secure-Login-Script-in-PHP-and-MySQL
*/
class Uservalidation {
public function __construct() {
$this->data=FALSE;
$this->auth=0;
$this->loginCheck();
}
// login function is provided a hashed password directly from the browser (see uservalidation.js)
public function login($email,$hash) {
global $DB;
if($email=filter_var($email,FILTER_VALIDATE_EMAIL)) {
$email=$DB->real_escape_string($email);
$hash=$DB->real_escape_string($hash);
if($user=sql_fetch("SELECT * FROM users WHERE user_email='$email' AND user_hash='$hash' AND user_status>1 LIMIT 1")) {
// Successful login
$user_browser=$_SERVER['HTTP_USER_AGENT'];
$_SESSION['session_email']=$user['user_email'];
$_SESSION['session_hash']=hash('sha512',$user['hash'].$user_browser);
$this->data=$user;
$this->auth=$user['user_auth'];
return TRUE;
} else {
// Email and hash does not match
// Record attempt in login_attempts table
return FALSE;
}
} else {
// Not a valid email address
return FALSE;
}
}
public function logout() {
$this->destroySession();
$this->data=FALSE;
$this->auth=0;
}
// Validate user session
private function loginCheck() {
$user_browser=$_SERVER['HTTP_USER_AGENT'];
if($user=$this->getUser($_SESSION['session_email'])) {
$user_hash=hash('sha512',$user['user_hash'].$user_browser);
if(hash_equals($user_hash,$_SESSION['session_hash'])) {
// Successful match
$this->data=$user;
$this->auth=$user['user_auth'];
return TRUE;
} else {
// Hashes does not match
return FALSE;
}
} else {
// User doesn't exist
return FALSE;
}
}
// Get data for specific user (either by email, uid or hash)
public function getUser($string) {
global $DB;
//echo "User: $string";
if($email=filter_var($string,FILTER_VALIDATE_EMAIL)) {
$checkuser=sql_fetch("SELECT * FROM users WHERE user_email='$email' LIMIT 1");
} elseif($id=filter_var($string,FILTER_VALIDATE_INT)) {
$checkuser=sql_fetch("SELECT * FROM users WHERE uid='$id' LIMIT 1");
} else {
$hash=$DB->real_escape_string($string);
$checkuser=sql_fetch("SELECT * FROM users WHERE user_hash='$hash' LIMIT 1");
}
return $checkuser;
}
private function clearSession() {
// Unset all of the session variables.
$_SESSION=array();
}
private function destroySession() {
$this->clearSession();
// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if(ini_get("session.use_cookies")) {
$params=session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// Finally, destroy the session.
session_destroy();
}
}
?>
登录.php
<?php
require_once 'global.php';
// Process login (field "p" is created in uservalidation.js and contain the SHA512 hash of the password so raw password will never be sent to server)
if(isset($_POST['user_email']) && isset($_POST['p'])) {
if($USER->login($_POST['user_email'],$_POST['p'])) {
//header('location:index.php');
$html.="<pre>";
$html.=print_r($_SESSION,TRUE);
$html.=print_r($USER,TRUE);
$html.="</pre>";
$html.="<a href='index.php'>Go on!</a>";
} else {
$html="<p>Could not log in...</p>";
}
} else {
$theform=new htmlForm('login.php');
$theform->addInput('Username',array('type' => 'email', 'name' => 'user_email', 'required' => '', 'autocomplete' => 'off'));
$theform->addInput('Password',array('type' => 'password', 'name' => 'password', 'required' => ''));
$theform->addInput(FALSE,array('type' => 'button', 'value' => 'Login', 'class' => 'button', 'onclick' => 'formhash(this.form);'));
$html=$theform->render();
}
// Render Page
//=================================================================================================
?>
<!doctype html>
<html class="no-js" lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NGI Skunkworks</title>
<link rel="stylesheet" href="css/foundation.css">
<link rel="stylesheet" href="css/app.css">
<link rel="stylesheet" href="css/icons/foundation-icons.css" />
</head>
<body>
<?php require '_menu.php'; ?>
<div class="row">
<br>
<div class="large-12 columns">
<?php echo $html; ?>
</div>
</div>
<script src="js/vendor/jquery.js"></script>
<script src="js/vendor/what-input.js"></script>
<script src="js/vendor/foundation.js"></script>
<script src="js/app.js"></script>
<script src="js/sha512.js"></script>
<script src="js/uservalidation.js"></script>
</body>
</html>
【问题讨论】:
-
那么您在包含其他文件之后开始会话。总是
start_session()FIRST -
本题文字过多,代码不足。
-
现在添加了代码示例的链接。无法粘贴到文本框中.....不,会话先于其他任何内容开始。
-
@MattiasOrmestad 您是否启用了完整的错误报告?
-
@tereško,我从 loginCheck 方法得到未定义的索引 (session_email)
标签: php oop session session-variables superglobals