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?
XenForo登录验证
- 写回答
- 好问题 0 提建议
- 追加酬金
- 关注问题
- 邀请回答
-
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, onlyuser_id
to determine the user. The usernames are stored inxf_user
. In order to compare the username & password, you'll need toSELECT user_id FROM xf_user WHERE username LIKE ...
and using that you'll need toSELECT data FROM xf_user_authenticate WHERE user_id LIKE ...
, then simply usepassword_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 ofpassword_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的项目开发该怎么把前段后端和业务层分离