dsxon40042 2014-05-30 01:11
浏览 213

XenForo登录验证

I'm working on a 3rd party application, and I need to make a stand alone login authentication. I don't want to setup a session or create any local data vars of the sort, I just want to check the username/password for a match. The issue standing is that the XF authentication system doesn't make much sense to me. I've looked around the official XF website, but I haven't gathered much. I understand that password/salt data is stored in the xf_user_authentication table, but I don't know what to make of it. Would anyone be so kind as to explain to me how passwords are formed and what does what within this table?

  • 写回答

1条回答 默认 最新

  • dongsun2789 2018-03-12 20:28
    关注

    Posting this answer for anyone who comes across this in the future.

    XenForo stores the users passwords in xf_user_authenticate, but without usernames, only user_id to determine the user. The usernames are stored in xf_user. In order to compare the username & password, you'll need to SELECT user_id FROM xf_user WHERE username LIKE ... and using that you'll need to SELECT data FROM xf_user_authenticate WHERE user_id LIKE ..., then simply use password_verify(); to compare the sanitized user input to the hashed password stored in the database. Do note that the hashed passwords are store in a .bin blob along with the cost and salt values used to hash them, these are default values of password_verify();, so all you'll really need to do prior to comparison is to strip the rest of the characters away from the hashed password itself using $password = substr($password, 22, -3); ($password being the string from the database) as the hashed password starts after 22 characters in with 3 trailing characters at the end, the hash being 60 characters long with the total blob character count being 85.

    I as well was tasked recently with developing a login verification system that would work with the user accounts that were created on the register page on the forum. This way you can attach those scripts with the correct database connection info to any external website, even on a different server (assuming you're not using shared hosting) and successfully verify a users login request against the forum account information. From there you'll have no problems pulling things like profile information or the accounts avatars, or even their post history!

    Here's what I've come up with:

    First up, the obvious. Setup your database connection:

    <?
        define('DB_SERVER', 'localhost');
        define('DB_USER', 'phpMyAdmin Login Here');
        define('DB_PASS', 'phpMyAdmin Password Here');
        define('DB_DATABASE', 'Typically [user_xenpubdatabase]');
    
        $conn = mysqli_connect(DB_SERVER, DB_USER, DB_PASS, DB_DATABASE);
            if (!$conn) {
                die('Database connection failed: ' . mysqli_connect_error());
    ?>
    

    Now I've also opted to use functions and store those separate from the login form, so when a user submits, the functions.php is included on login.

    Here's my functions:

    <?php
    function sanitize($input, $conn){
        $input = trim($input); // removing spaces
        $strlenght = strlen($input);//get the length of the input
        for($i = 0; $i <= $strlenght; $i++) {//foreach sting char
            $input = stripslashes($input); // remove backslashes
        }
        $input = htmlspecialchars($input); // make sure code gets declared
        $input = mysqli_real_escape_string($conn, $input); //disable code execution
        return $input;
    }
    
    function checkForExistingAccount($username, $conn){
        if ($stmt = mysqli_prepare($conn, "SELECT id from users where username = ?")) {
    
            mysqli_stmt_bind_param($stmt, 's', $username);
    
            mysqli_stmt_execute($stmt);
    
            mysqli_stmt_store_result($stmt);
    
            if (mysqli_stmt_num_rows($stmt) > 0){//if an account returned then rip the username already exists...
                mysqli_stmt_close($stmt);
                return true;//so return true
            }
            mysqli_stmt_close($stmt);
        }
        return false;
    
    }
    
    function checkUsername($username, $conn){
    
        if ($stmt2 = mysqli_prepare($conn, "SELECT user_id FROM xf_user WHERE username = ?")){
            mysqli_stmt_bind_param($stmt2, "s", $username);
    
            mysqli_stmt_execute($stmt2);
    
            mysqli_stmt_store_result($stmt2);
            if (mysqli_stmt_num_rows($stmt2) > 0){
                mysqli_stmt_close($stmt2);
                return true;
            }
        }
        return false;
    }
    function getPassword($username, $conn){
        if ($stmt2 = mysqli_prepare($conn, "SELECT data FROM xf_user_authenticate WHERE username = ?")){
            mysqli_stmt_bind_param($stmt2, "s", $username);
    
            mysqli_stmt_execute($stmt2);
    
            mysqli_stmt_bind_result($stmt2, $password);
            mysqli_stmt_fetch($stmt2);
    
            mysqli_stmt_close($stmt2);
            $password = substr($password, 22, -3);
            return $password;
        }
    
    }
    
    function checkPassword($user_pass, $hashed_pass){
        if (password_verify($user_pass, $hashed_pass)) {
            return true;
        }
        return false;
    
    }
    

    From there, my login script looks as follows:

    if (isset($_POST['login'])){
        include 'dbs.php';
        include 'functions.php';
        if (!empty($username = sanitize($_POST['username'], $conn)) && !empty($password = sanitize($_POST['password'], $conn))) {
            if (checkUsername($username, $conn)) {
                if (!empty($dbs_password = getPassword($username, $conn))) {
                    if (checkPassword($password, $dbs_password)) {
                        session_start();
                        $_SESSION['active'] = 1;//never use true, some browsers are buggy with that.
                        mysqli_close($conn);//close conn then redirect
                        header('location: ../index.php');
                    } else {
                        echo '<div class="danger">Sorry, you have entered wrong information</div>';
                    }
                }
            } else {
                echo '<div class="danger">Sorry, no user found with the username: ' . $username . '</div>';
            }
        }
        else{
            echo '<div class="danger">You have to fill in all fields*</div>';
        }
        mysqli_close($conn);
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 python按要求编写程序
  • ¥15 Python输入字符串转化为列表排序具体见图,严格按照输入
  • ¥20 XP系统在重新启动后进不去桌面,一直黑屏。
  • ¥15 opencv图像处理,需要四个处理结果图
  • ¥15 无线移动边缘计算系统中的系统模型
  • ¥15 深度学习中的画图问题
  • ¥15 java报错:使用mybatis plus查询一个只返回一条数据的sql,却报错返回了1000多条
  • ¥15 Python报错怎么解决
  • ¥15 simulink如何调用DLL文件
  • ¥15 关于用pyqt6的项目开发该怎么把前段后端和业务层分离