我尝试添加PDO::PARAM_STR
和$stmt->bindParam(':username', $username, PDO::PARAM_INT);
这些都没有奏效。
我收到以下错误:
注意:未定义的属性: 在... /AutoLogin.php上的Foundationphp \ Sessions \ AutoLogin :: $ sess_ukey 第107行
注意:未定义的属性: Foundationphp \ Sessions \ AutoLogin :: $ col_ukey in ... / AutoLogin.php on 第191行
致命错误:带有消息的未捕获异常'PDOException' 'SQLSTATE [42000]:语法错误或访问冲突:1064您有 SQL语法错误;查看与您的手册相对应的手册 MySQL服务器版本,用于在'in附近使用正确的语法 ..... /第105行的AutoLogin.php
PDOException:SQLSTATE [42000]:语法错误或访问冲突:1064 您的SQL语法有错误;检查手册 对应于您的MySQL服务器版本,以便使用正确的语法 在'FROM users WHERE username ='david''附近的第1行 ...... /第105行的AutoLogin.php
代码如下:
<?php
namespace Foundationphp\Sessions;
class AutoLogin
{
use PersistentProperties;
/**
* @var \PDO Database connection
*/
protected $db;
/**
* @var int Position at which user key is inserted in single-use token
*/
protected $token_index;
/**
* @var int Number of days the autologin cookie remains valid
*/
protected $lifetimeDays = 30;
/**
* @var int Unix timestamp for when the cookie expires
*/
protected $expiry;
/**
* @var string Path to be set in the autologin cookie
*/
protected $cookiePath = '/persistent';
/**
* @var string Domain for autologin cookie
*/
protected $domain = '';
/**
* @var null Whether cookie should be sent only over a secure connection
*/
protected $secure = null;
/**
* @var bool Whether cookie should be accessible only through HTTP protocol
*/
protected $httponly = true;
/**
* Constructor
*
* Requires a PDO connection to the database where the user's credentials,
* session data, and autologin details are stored.
*
* @param \PDO $db Datatbase connection
* @param int $token_index Position at which user key is to be inserted in token
*/
public function __construct(\PDO $db, $token_index = 0)
{
$this->db = $db;
if ($this->db->getAttribute(\PDO::ATTR_ERRMODE) !== \PDO::ERRMODE_EXCEPTION) {
$this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
}
$this->token_index = ($token_index <= 31) ? $token_index : 31;
$this->expiry = time() + ($this->lifetimeDays * 60 * 60 * 24);
}
/**
* Creates a persistent login for the user
*
* The login process gets the user's unique key (an 8-digit
* hexadecimal string), and stores it with a random 32-digit
* string. Both values are merged and appended to the
* username to create a single-use token that's stored as a
* cookie in the user's browser.
*/
public function persistentLogin()
{
// Get the user's ID
if ($_SESSION[$this->sess_ukey] = $this->getUserKey()) {
$this->getExistingData();
// Generate a random 32-digit hexadecimal token
$token = $this->generateToken();
// Store the token and user's ID in the database
$this->storeToken($token);
// Store the single-use token as a cookie in the user's browser
$this->setCookie($token);
$_SESSION[$this->sess_persist] = true;
unset($_SESSION[$this->cookie]);
}
}
/**
* Check if a valid persistent cookie has been presented
*
* If the cookie exists, the user's unique key is retrieved
* from the database and removed from the single-use token.
* Before checking for a matching pair, expired tokens are
* deleted from the database. If the token is valid, data from
* the stored session is retrieved and added to the current
* session.
*/
public function checkCredentials()
{
// Do nothing if the cookie doesn't exist
if (isset($_COOKIE[$this->cookie])) {
if ($storedToken = $this->parseCookie()) {
// Delete expired tokens before checking the current one
$this->clearOld();
// Log in the user if the token hasn't been used
if ($this->checkCookieToken($storedToken, false)) {
// Log in the user
$this->cookieLogin($storedToken);
// Generate and store a fresh single-use token
$newToken = $this->generateToken();
$this->storeToken($newToken);
$this->setCookie($newToken);
} elseif ($this->checkCookieToken($storedToken, true)) {
// If the token has already been used, suspect an attack,
// delete all tokens associated with the user key,
// and invalidate the current session.
$this->deleteAll();
$_SESSION = [];
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 86400, $params['path'], $params['domain'],
$params['secure'], $params['httponly']);
session_destroy();
// Invalidate the autologin cookie
setcookie($this->cookie, '', time() - 86400, $this->cookiePath,
$this->domain, $this->secure, $this->httponly);
}
}
}
}
/**
* Logs out the user from all sessions or just the current one
*
* @param bool $all True if all sessions are to be deleted
*/
public function logout($all = true)
{
if ($all) {
$this->deleteAll();
} else {
$token = $this->parseCookie();
$sql = "UPDATE $this->table_autologin SET $this->col_used = 1
WHERE $this->col_token = :token";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':token', $token);
$stmt->execute();
}
setcookie($this->cookie, '', time() - 86400, $this->cookiePath,
$this->domain, $this->secure, $this->httponly);
}
/**
* Retrieves the user's ID from the users table
*
* @return string User's ID
*/
protected function getUserKey()
{
$sql = "SELECT $this->col_ukey FROM $this->table_users
WHERE $this->col_name = :username";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':username', $_SESSION[$this->sess_uname], PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetchColumn();
}
/**
* Retrieve the user's data from the most recent session
*/
protected function getExistingData()
{
$sql = "SELECT $this->col_data FROM $this->table_autologin
WHERE $this->col_ukey = :key
ORDER BY $this->col_created DESC";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':key', $_SESSION[$this->sess_ukey]);
$stmt->execute();
// Get the most recent result
if ($data = $stmt->fetchColumn()) {
// Populate the $_SESSION superglobal array
session_decode($data);
}
// Release the database connection for other queries
$stmt->closeCursor();
}
/**
* Generates a random 32-character string for the single-use token
*
* @return string 32-character hexadecimal string
*/
protected function generateToken()
{
return bin2hex(openssl_random_pseudo_bytes(16));
}
/**
* Stores the user's ID and single-use token in the database
*
* @param string $token 32-character hexadecimal string
*/
protected function storeToken($token)
{
try {
$sql = "INSERT INTO $this->table_autologin
($this->col_ukey, $this->col_token)
VALUES (:key, :token)";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':key', $_SESSION[$this->sess_ukey]);
$stmt->bindParam(':token', $token);
$stmt->execute();
} catch (\PDOException $e) {
if ($this->db->inTransaction()) {
$this->db->rollBack();
}
throw $e;
}
}
/**
* Creates and stores autologin cookie in user's browser
*
* @param string $token 32-character single-use token
*/
protected function setCookie($token)
{
$merged = str_split($token);
array_splice($merged, hexdec($merged[$this->token_index]), 0, $_SESSION[$this->sess_ukey]);
$merged = implode('', $merged);
$token = $_SESSION[$this->sess_uname] .'|' . $merged;
setcookie($this->cookie, $token, $this->expiry,
$this->cookiePath, $this->domain, $this->secure,
$this->httponly);
}
/**
* Removes the user_key from the cookie token
*
* @return array|bool Array containing the username and token, or false
*/
protected function parseCookie()
{
// Separate the username and submitted token
$parts = explode('|', $_COOKIE[$this->cookie]);
$_SESSION[$this->sess_uname] = $parts[0];
$token = $parts[1];
// Proceed only if the username is valid
if ($_SESSION[$this->sess_ukey] = $this->getUserKey()) {
// Remove the user's ID from the submitted cookie token
return str_replace($_SESSION[$this->sess_ukey], '', $token);
} else {
return false;
}
}
/**
* Deletes records older than the value set in the $lifetimeDays property
*/
protected function clearOld()
{
$sql = "DELETE FROM $this->table_autologin
WHERE DATE_ADD($this->col_created, INTERVAL :expiry DAY) < NOW()";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':expiry', $this->lifetimeDays);
$stmt->execute();
}
/**
* Checks whether the single-use token has already been used
*
* @param string $token 32-digit single-use token
* @param bool $used
* @return bool Depends on value of $used
*/
protected function checkCookieToken($token, $used)
{
$sql = "SELECT COUNT(*) FROM $this->table_autologin
WHERE $this->col_ukey = :key AND $this->col_token = :token
AND $this->col_used = :used";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':key', $_SESSION[$this->sess_ukey]);
$stmt->bindParam(':token', $token);
$stmt->bindParam(':used', $used, \PDO::PARAM_BOOL);
$stmt->execute();
if ($stmt->fetchColumn() > 0) {
return true;
} else {
return false;
}
}
/**
* Delete all entries in autologin table related with the user's ID
*/
protected function deleteAll()
{
$sql = "DELETE FROM $this->table_autologin WHERE $this->col_ukey = :key";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':key', $_SESSION[$this->sess_ukey]);
$stmt->execute();
}
/**
* Logs in the user if the single-use cookie is valid
*
* @param string $token 32-character single-use token
*/
protected function cookieLogin($token)
{
try {
$this->getExistingData($_SESSION[$this->sess_ukey]);
$sql = "UPDATE $this->table_autologin SET $this->col_used = 1
WHERE $this->col_ukey = :key AND $this->col_token = :token";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':key', $_SESSION[$this->sess_ukey]);
$stmt->bindParam(':token', $token);
$stmt->execute();
session_regenerate_id(true);
$_SESSION[$this->cookie] = true;
unset($_SESSION[$this->sess_auth]);
unset($_SESSION[$this->sess_revalid]);
unset($_SESSION[$this->sess_persist]);
} catch (\PDOException $e) {
if ($this->db->inTransaction()) {
$this->db->rollBack();
}
throw $e;
}
}
}
任何建议都会非常感谢!
答案 0 :(得分:4)
因为,您需要使用\
来处理PDO,主要是因为在您的应用程序类命名空间中没有名为PDO
的类。这样做是为了查找PDO
命名空间中的\
类,它就在这里。你现在应该做这样的事情:
$stmt->bindParam(':username', $username, \PDO::PARAM_INT);
要不要一次又一次地这样做,你可以这样做:
定义use PDO;
之后和namespace
关键字之前 class
。