重要
以下の回答のアドバイスに従った後、クライアントは問題なくログインできましたが、保護されたページを実際にナビゲートしようとはしませんでした。後でログインしようとすると、「ログインしてください」というエラーが表示され、以前のようにログインに戻りました。多くの頭を悩ませた後、信じられないほど単純なことが頭に浮かびました。クライアントはhttp://www.example.com/adminでサイトにアクセスしており、ログインスクリプトのすべてがhttp://example.comにリダイレクトされていたため、セッションは探していた Cookie が別のドメインに設定されていました。これは、彼が最初にログインする際に問題が発生し、その後は問題が発生しなかった理由も説明しています。スクリプトにより、www.
簡単な修正は、.htaccess ファイルを作成して www を削除することでした。問題は解決しました。もちろん、これはログイン スクリプト内で処理することもできます。これは、将来の使用のために改善する予定です。
元の投稿
自作の CMS とログイン システムを使用して、PHP と MySQL ベースのサイトを開発しています。私の CMS はすべてのクライアントに固有のものであり、多くの人を喜ばせてきました。残念ながら、私のログイン システムには同じことが当てはまりません。以下は長い投稿ですが、解決策を見つけるために詳細をカバーする必要があります. 我慢して..
システムは、少し重くはないにしても、かなり簡単です。各ユーザーは、SALT と一緒に MySQL テーブルに格納されたソルト ハッシュを持っています。ユーザーがログインすると、SALT が取得され、送信されたパスワードがソルト付きハッシュになります。
送信されたソルト付きハッシュがテーブルに格納されているものと一致する場合、ユーザーは認証されます。名前、最後の IP アドレス、アカウント レベル (ほとんどのサイトで 3 レベル) などの詳細は、セッション変数に割り当てられた配列に格納されます。次に、ログインした制限付きサイト (メンバーのみまたは管理者/CMS) のランディング ページにリダイレクトされます。
セキュリティで保護されたページには、詳細を含むセッション変数が存在するかどうかを確認する小さな auth.php ファイルが含まれています。そうでない場合は、そのサイトのログイン フォームにリダイレクトされ、「ログインしてください」というエラー メッセージが表示されます。存在する場合は続行が許可され、配列に格納されている詳細が変数に割り当てられます。
多くのユーザーから報告されている問題は、「ログインしてください」というエラー メッセージが表示されてログイン フォームに戻されないようにするために、何度もログインする必要があることです。サイトにアクセスして、同じエラーでランダムにログインに戻されます。したがって、セッション変数は、サイトの通常の使用中に何らかの理由で設定されていないか、クリアされているようです。
最初の問題は、多数のデバイスとネットワークで発生したことがなく、クライアントのオフィスでラップトップを使用して目撃したことがあります。モバイルホットスポットに接続してもらいましたが、変化はありませんでした。しかし、彼らは私のラップトップとホットスポット接続を使用して問題なくログインできました. 残念ながら、ラップトップを使用してネットワークに接続できなかったため、その変数を除外できませんでした.
*注意 - *問題のあるクライアントが正しい認証情報で 2 ~ 3 回ログインすると、システムは正常に動作するということを最初に言い忘れました。ブラウザを開いたままログインしようとすると、その後は問題なく実行される傾向があります。また、ログイン ページはセッションを破棄します。
ログイン スクリプトから始まる各ステージのコードを次に示します。
login.php
<?php
putenv("TZ=US/Eastern");
if (array_key_exists('site', $_POST)) {
$authenticate = new loginUser($_POST['username'], $_POST['password'], $_POST['site'], $_SERVER['REMOTE_ADDR']);
}
//Authenticate and log-in
class loginUser {
private $memDB, $username, $password, $site, $ip_address;
//Clean input variables
private function clean($str) {
$str = @trim($str);
if(get_magic_quotes_gpc()) {
$str = stripslashes($str);
}
return $str;
}
//Construct variables
function __construct($username, $password, $site, $ip_address) {
session_start();
$this->memDB = new PDO('mysql:host=localhost;dbname=exampleDB', 'exampleUser', 'examplePassword');
$this->username = $this->clean($username);
$this->password = $this->clean($password);
$this->site = $site;
$this->ip_address = $ip_address;
$this->authUser();
}
//Validate username
private function validateUsername($username) {
$checkUsername = $this->memDB->prepare("SELECT COUNT(*) FROM accounts WHERE username = ?");
$checkUsername->execute(array($username));
return $checkUsername->fetchColumn();
}
//Obtain and set account details
private function accountDetails() {
$fetchAccountDetails = $this->memDB->prepare("SELECT id, name_f, name_l, ipAddr, lastLogin, accountLevel, isActive
FROM accounts WHERE username = ?");
$fetchAccountDetails->execute(array($this->username));
$accountDetails = $fetchAccountDetails->fetch();
$this->updateLogin();
return $accountDetails;
}
//Update last login details
private function updateLogin() {
$updateLogin = $this->memDB->prepare("UPDATE accounts SET ipAddr = ?, lastLogin = DATE_ADD(NOW(), INTERVAL 1 HOUR) WHERE username = ?");
$updateLogin->execute(array($this->ip_address, $this->username));
}
public function authUser() {
$loginErr = array(); //Array for holding login error message
$loginErrFlag = false; //Boolean for error
//Validate submitted $_POST elements
if (!$this->username) {
$loginErr[] = "Username missing";
$loginErrFlag = true;
}
if (!$this->password) {
$loginErr[] = "Password missing";
$loginErrFlag = true;
}
if ($this->username && $this->validateUsername($this->username) == 0) {
$loginErr[] = "Username invalid";
$loginErrFlag = true;
}
if (!$loginErrFlag) {
//Fetch the password and SALT to compare to entered password
$validatePW = $this->memDB->prepare("SELECT password, salt FROM accounts WHERE username = ? LIMIT 1");
$validatePW->execute(array($this->username));
$passwordResult = $validatePW->fetch();
$dbPW = $passwordResult['password'];
$dbSalt = $passwordResult['salt'];
//Compare entered password to SALT + hash
$hashPW = hash('sha512', $dbSalt . $this->password);
if ($hashPW === $dbPW) {
//Logged in
$_SESSION['CVFD-USER-DETAILS'] = $this->accountDetails();
//Redirect to secure landing page for log-in origin (Members or Admin)
//Adding SID is a recent attempt to handle log-in problems
header("Location: http://example.com/$this->site/$this->site-main.php?" . SID);
//session_write_close() was here but was removed
exit();
} else {
//Password invalid
$loginErr[] = "Please check your password and try again";
$_SESSION['CVFD_LOGIN_ERR'] = $loginErr;
//Redirect to the log-in for the origin
header("Location: http://example.com/$this->site");
session_write_close();
exit();
}
} else {
$_SESSION['CVFD_LOGIN_ERR'] = $loginErr;
header("Location: http://example.com/$this->site");
session_write_close();
exit();
}
}
}
?>
auth.php
<?php
session_start();
if (!isset($_SESSION['CVFD-USER-DETAILS']) || $_SESSION['CVFD-USER-DETAILS'] == '') {
//Not logged in
$_SESSION['CVFD_LOGIN_ERR'] = array('Please login');
header('Location: http://example.com/members');
session_write_close();
exit();
} else {
$userDetails = $_SESSION['CVFD-USER-DETAILS']; //Assign user details array to variable
//Check to see if account is active
$accountStatus = $userDetails['isActive'];
$accountLevel = $userDetails['accountLevel'];
if ($accountStatus == 0) {
//Account is not yet active (pending Admin activation)
$_SESSION['CVFD_LOGIN_ERR'] = array('Your account is suspended or pending activation');
header('Location: http://example.com/members');
session_write_close();
exit();
} else {
$CVFDFirstName = $userDetails['name_f'];
$CVFDLastName = $userDetails['name_l'];
$CVFDLastLogin = date("m/d/Y H:i:s", strtotime($userDetails['lastLogin']));
$CVFDAccountLevel = $userDetails['accountLevel'];
$CVFDIPAddr = $userDetails['ipAddr'];
}
}
?>
安全なファイルに auth.php を含める方法は次のとおりです。
<?php
if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler"); else ob_start();
require($_SERVER['DOCUMENT_ROOT'] . '/members/includes/handlers/handler.auth.php');
どんな助けでも大歓迎です。なかなかの謎..
ありがとう!