- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我尝试添加 PDO::PARAM_STR
和 $stmt->bindParam(':username', $username, PDO::PARAM_INT);
这些都没有用。
我收到以下错误:
Notice: Undefined property: Foundationphp\Sessions\AutoLogin::$sess_ukey in .... /AutoLogin.php on line 107
Notice: Undefined property: Foundationphp\Sessions\AutoLogin::$col_ukey in .../AutoLogin.php on line 191
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' in ...../AutoLogin.php on line 195
PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM users WHERE username = 'david'' at line 1 in ..../AutoLogin.php on line 195
代码如下:
<?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;
}
}
}
如有任何建议,我们将不胜感激!
最佳答案
因为,您需要使用 \
来处理 PDO,主要是因为在您的应用程序类命名空间中没有名为 PDO
的此类。它所做的是在 \
命名空间中查找 PDO
类,这就是它所在的位置。你现在应该做这样的事情:
$stmt->bindParam(':username', $username,\PDO::PARAM_INT);
要停止一次又一次地这样做,你可以这样做:
使用 PDO;
在定义 namespace
之后和 class
关键字之前。
关于php - 未定义的属性,PDOException 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34535866/
你能比较一下属性吗 我想禁用文本框“txtName”。有两种方式 使用javascript,txtName.disabled = true 使用 ASP.NET, 哪种方法更好,为什么? 最佳答案 我
Count 属性 返回一个集合或 Dictionary 对象包含的项目数。只读。 object.Count object 可以是“应用于”列表中列出的任何集合或对
CompareMode 属性 设置并返回在 Dictionary 对象中比较字符串关键字的比较模式。 object.CompareMode[ = compare] 参数
Column 属性 只读属性,返回 TextStream 文件中当前字符位置的列号。 object.Column object 通常是 TextStream 对象的名称。
AvailableSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。 object.AvailableSpace object 应为 Drive 
Attributes 属性 设置或返回文件或文件夹的属性。可读写或只读(与属性有关)。 object.Attributes [= newattributes] 参数 object
AtEndOfStream 属性 如果文件指针位于 TextStream 文件末,则返回 True;否则如果不为只读则返回 False。 object.A
AtEndOfLine 属性 TextStream 文件中,如果文件指针指向行末标记,就返回 True;否则如果不是只读则返回 False。 object.AtEn
RootFolder 属性 返回一个 Folder 对象,表示指定驱动器的根文件夹。只读。 object.RootFolder object 应为 Dr
Path 属性 返回指定文件、文件夹或驱动器的路径。 object.Path object 应为 File、Folder 或 Drive 对象的名称。 说明 对于驱动器,路径不包含根目录。
ParentFolder 属性 返回指定文件或文件夹的父文件夹。只读。 object.ParentFolder object 应为 File 或 Folder 对象的名称。 说明 以下代码
Name 属性 设置或返回指定的文件或文件夹的名称。可读写。 object.Name [= newname] 参数 object 必选项。应为 File 或&
Line 属性 只读属性,返回 TextStream 文件中的当前行号。 object.Line object 通常是 TextStream 对象的名称。 说明 文件刚
Key 属性 在 Dictionary 对象中设置 key。 object.Key(key) = newkey 参数 object 必选项。通常是 Dictionary 
Item 属性 设置或返回 Dictionary 对象中指定的 key 对应的 item,或返回集合中基于指定的 key 的&
IsRootFolder 属性 如果指定的文件夹是根文件夹,返回 True;否则返回 False。 object.IsRootFolder object 应为&n
IsReady 属性 如果指定的驱动器就绪,返回 True;否则返回 False。 object.IsReady object 应为 Drive&nbs
FreeSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。只读。 object.FreeSpace object 应为 Drive 对象的名称。
FileSystem 属性 返回指定的驱动器使用的文件系统的类型。 object.FileSystem object 应为 Drive 对象的名称。 说明 可
Files 属性 返回由指定文件夹中所有 File 对象(包括隐藏文件和系统文件)组成的 Files 集合。 object.Files object&n
我是一名优秀的程序员,十分优秀!