简体   繁体   English

会话/cookie 用户定期退出

[英]Session/cookie users getting periodically logged out

My users have been getting logged out from my site.我的用户已从我的网站注销。 This happens when when someone logs in from another device.当有人从另一台设备登录时会发生这种情况。 I looked into it and noticed someone from a remote IP has been able to log into my website as different users.我查看了它并注意到来自远程 IP 的某个人能够以不同的用户身份登录我的网站。

I do not know if I am intentionally being targeted, or if it is somehow an error in my code.我不知道我是故意成为目标,还是我的代码中存在某种错误。 I would like to know how to properly set up session cookies in a secure manner to prevent this from occurring.我想知道如何以安全的方式正确设置会话 cookie 以防止发生这种情况。

  1. My cookies are HTTP only我的 cookie 只是 HTTP

  2. I also don't believe it is a man-in-the-middle attack, since multiple users from different areas are getting logged out .我也不相信这是中间人攻击,因为来自不同地区的多个用户正在注销 My website is SSL secured.我的网站是 SSL 保护的。

  3. I don't believe it is a brute force attack.我不相信这是一个蛮力攻击。 Sometimes when I log in, within 30 seconds I am logged out again and the remote IP is logged in.有时我登录时,在30秒内我再次注销登录了远程IP。

  4. I don't believe he has access to any passwords.我不相信他可以访问任何密码。 Everything is hashed in the database and the only thing stored on the client is the session HTTP ONLY cookie token.一切都在数据库中散列,唯一存储在客户端上的是会话 HTTP ONLY cookie 令牌。

I am very stuck.我很困。

Here is my login script that checks the user's credentials and sets the session:这是我的登录脚本,用于检查用户的凭据并设置会话:

//database connection is $db_connect

//Creates a random String
function generateRandomString() {
    $length = rand(25, 30);
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

//Grab email, password, IP address
$email_attempt=strtoupper(preg_replace('#[^a-z0-9\.\@\_\-\+]#i', '', $_POST['e']));
$password_attempt=$_POST["p"];
$user_IP = preg_replace('#[^0-9.\:]#', '', getenv('REMOTE_ADDR'));


//Call the database
$sql = "SELECT password, userID FROM user_data WHERE email='$email_attempt' LIMIT 1";
$query = mysqli_query($db_connect, $sql);
if(mysqli_num_rows($query)>0)
{

    //Get the ID and hashed password from database
    while($row = $query->fetch_assoc()) {
        $password_db=$row["password"];
        $userID_db=$row["userID"];
    }


    //Verify Login using password verify
    if(password_verify($password_attempt, $password_db)==true){

        //remove any previous sessions for the user
        $sql = "DELETE FROM user_sessions WHERE userID='$userID_db'";
        $query = mysqli_query($db_connect, $sql);


        //Clear any current cookies from client
        if(isset($_COOKIE["user"]) && isset($_COOKIE["token"])) {
            setcookie("user", '', strtotime( '-5 days' ), '/');
            setcookie("token", '', strtotime( '-5 days' ), '/');
        }
        session_destroy();


        // Set Session data to an empty array
        $_SESSION = array();


        //create a new token, set new session and cookies 
        $token=generateRandomString();
        $_SESSION['user'] = $userID_db;
        $_SESSION['token'] = $token;
        setcookie("user", $userID_db, strtotime( '+3 days' ), "/", "", "", TRUE);
        setcookie("token", $token, strtotime( '+3 days' ), "/", "", "", TRUE);


        //Hash the token to store in the database
        $token_hash=password_hash($token, PASSWORD_DEFAULT);

        //Store session into database
        $sql = "INSERT INTO user_sessions 
            (userID, session_token, IP, loginDate) 
            VALUES 
            ('$userID_db','$token_hash','$user_IP', '$current_date')";

        $query = mysqli_query($db_connect, $sql);

        header("Location: dashboard.php");
    }

    else
    {
        echo 'wrong_credentials';
    }
}

Here is my code to evaluate a user and see if they are logged in by examining the session and cookies;这是我的代码,用于评估用户并通过检查会话和 cookie 来查看他们是否已登录;

//start session
session_start();

$user_ok = false;
$clientID = "";
$token = "";
$user_IP = preg_replace('#[^0-9.\:]#', '', getenv('REMOTE_ADDR'));

if(isset($_SESSION["user"]) && isset($_SESSION["token"])) {
    //Get session
    $clientID = preg_replace('#[^a-z0-9]#i', '', $_SESSION['user']);
    $token = preg_replace('#[^a-z0-9]#i', '', $_SESSION['token']);


    // Verify the user with session data
    $user_ok = checkUser($db_connect,$clientID,$token,$user_IP);



} else if(isset($_COOKIE["user"]) && isset($_COOKIE["token"])){

    //Set session from cookie
    $_SESSION['user'] = preg_replace('#[^a-z0-9]#i', '', $_COOKIE['user']);
    $_SESSION['token'] = preg_replace('#[^a-z0-9]#i', '', $_COOKIE['token']);


    //Get session data
    $clientID =  preg_replace('#[^a-z0-9]#i', '', $_SESSION['user']);;
    $token =  preg_replace('#[^a-z0-9]#i', '', $_SESSION['token']);

    // Verify the user
    $user_ok = checkUser($db_connect,$clientID,$token,$user_IP);
} 




// User Verify function
function checkUser($db_connect,$user,$token,$ip){

    //Grab the session
    $sql = "SELECT session_token FROM user_sessions WHERE userID='$user' AND ip='$ip' LIMIT 1";
    $query = mysqli_query($db_connect, $sql);
    if(mysqli_num_rows($query)>0){

        $row=mysqli_fetch_row($query);

        $token_hashed=$row[0];

        //compare token given and hashed token
        if(password_verify($token,$token_hashed)==true)
        {
            return true;
        }

        else
        {
            return false;
        }
    } 

    else
    {
        return false;
    }
}

So my question: Is this code secure enough?所以我的问题是:这段代码足够安全吗?

How can I be more secure?我怎样才能更安全?

Also if you have any idea of what is happening in this puzzle please let me know, as I am getting destroyed .另外,如果您对这个谜题中发生的事情有任何想法,请告诉我,因为我正在被摧毁 Thank you in advance.先感谢您。

After some digging, I realized that the problem lies with trying to anchor a session to a single IP address.经过一番挖掘,我意识到问题在于尝试将会话锚定到单个 IP 地址。

We have CloudFlare running on our site, so getenv('REMOTE_ADDR') is sometimes returning CloudFlare's IP address instead of the client IP address.我们的站点上运行 CloudFlare,因此getenv('REMOTE_ADDR')有时会返回 CloudFlare 的 IP 地址而不是客户端 IP 地址。 This was causing the logouts.这导致了注销。

But I thought I could answer my own question based on the comments.但我想我可以根据评论回答我自己的问题。 To make the script more secure and stop periodic logouts, I should:为了使脚本更安全并停止定期注销,我应该:

  1. Always use prepared statements to protect against SQL injection始终使用准备好的语句来防止 SQL 注入
  2. Don't tie sessions to IP addresses because they may change (especially if on mobile)不要将会话绑定到 IP 地址,因为它们可能会改变(尤其是在移动设备上)

Occam's razor is the problem-solving principle that essentially states that simpler solutions are more likely to be correct than complex ones.奥卡姆剃刀是解决问题的原则,从本质上讲,简单的解决方案比复杂的解决方案更有可能是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM