用PHP,MySQL的基于日志的系统问题(Problems with PHP, MySQL base

2019-09-23 14:12发布

重要

依照下列答案的意见后,客户端能够登录,在没有任何问题,但并没有试图实际浏览的安全网页。 当他试图这样做以后,他回到了与“请登录”错误像以前一样登录项。 很多挠头之后,事情非常简单浮现在脑海-客户正在访问的网站与http://www.example.com/admin登录脚本,一切都重定向到http://example.com ,所以会议它一直在寻找另一个域设置的cookie。 这也解释了为什么他在第一次登录的问题,但没有后续时间 - 脚本重定向他的登录表单不带www。

速战速决是写.htaccess文件去除WWW,问题就迎刃而解了。 当然,这也登录脚本,我会改进将来使用内处理。

原帖

我开发PHP和MySQL基础的网站有家酿CMS和登录系统。 我的CMS是唯一的每一个客户,它已经相当的取悦观众 - 不幸的是,同样是没有我的登录系统也是如此。 下面是一个长期的职位,但我需要覆盖的细节,试图找到一个解决方案。 忍耐一下..

该系统是相当简单的,如果不是有点沉重。 每个用户具有存储在MySQL表盐腌哈希,旁边的盐。 当用户登录时,他们的盐是检索和提交的密码变成盐腌哈希。

如果提交的盐渍哈希值匹配存储在表中的一个,用户进行身份验证。 如他们的名字,最后一个IP地址和帐户级别(在大多数网站3级)的详细信息存储在分配给会话变量数组。 然后,他们将被重定向到受限制的站点的登陆页面,他们登录(只或管理/ CMS成员)。

安全网页包括检查是否含有他们的详细信息会话变量存在一个较小的auth.php文件。 如果不是,他们将被重定向到与读取的错误消息的网站的登录表格“请登录”。 如果存在,他们被允许继续并存储在数组中的细节被分配给变量。

许多用户报告的问题是,他们往往需要登录多次被反弹到保持登录形式与“请登录”错误信息,或者导航到另一个页面的安全现场并随机获得反弹具有相同的错误登录。 因此,会话变量似乎既不会得到设置或它正在正常使用本网站的过程中由于某种原因被清除。

第一个问题从来没有发生在我身上 - 在设备和网络的大量 - 和我一直在使用他们的笔记本电脑在客户的办公室亲眼目睹了。 我让他们连接到我的移动热点,也没有改变。 然而,他们能够登录,而无需使用我的笔记本电脑和我的热点连接的任何问题。 不幸的是,我无法用我的笔记本电脑连接到他们的网络,使变量不能被排除。

* 注- *我忘了最初提及的是,系统正常工作的问题客户,他们使用正确的凭据登录两次或三次之后。 随后的登录尝试,而他们的浏览器保持打开状态,往往没有问题后执行。 此外,登录页面破坏了会议。

下面是每个阶段,首先是登录脚本的代码:

的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');

任何帮助,将不胜感激。 相当一个谜..

谢谢!

Answer 1:

有一两件事,我跳出如下:

header('Location: http://example.com/members');
session_write_close();
exit();

我会放在session_write_close()调用之前header('location ...')

是否有任何“头已经发出”错误显示在你的日志呢?

我想到的另一件事是一些AJAX竞争状态。 任何异步调用回事登录页面?



Answer 2:

我不登录系统的方式是只使用会话ID,而不是存储在会议本身什么。 当在它们的散列用户代理数据的用户日志,其会话ID,他们的用户ID(对应于用户表)和期满时间被放入一张表,通常被称为“ACTIVE_USERS”,我然后有一个记录在头文件中包含在启动会话的每个管理员限制页面,获取用户的会话ID,并检查该会话ID是否在活跃用户表以及是否被检查的用户对具有相同的用户代理数据,过期时间不超过。 如果没有从该查询返回他们没有登录,并弹了出去。

这就是我最登录系统,使工作和我没有任何问题。



Answer 3:

成功! 还需要缩小正是变化导致的问题消失,但客户报告说,他不再有登录问题。

立即想到的最大的变化是删除session_write_close()几乎无处不在。 它可能已被放置在报头之后重定向代码的部分,或只是它具有本可能是原因。 我会尝试使用重定向之前放置它。

感谢所有您的建议



文章来源: Problems with PHP, MySQL based log-in system