我正在开发一个 3rd 方应用程序,我需要进行独立的登录身份验证。我不想设置会话或创建任何本地数据变量,我只想检查用户名/密码是否匹配。存在的问题是 XF 身份验证系统对我来说没有多大意义。我浏览了 XF 官方网站,但我没有收集到太多信息。我知道密码/盐数据存储在xf_user_authentication表中,但我不知道该怎么做。谁能向我解释一下密码是如何形成的,以及这张表中的内容是什么?
1 回答
为将来遇到此问题的任何人发布此答案。
XenForo 将用户密码存储在 中xf_user_authenticate,但没有用户名,仅user_id用于确定用户。用户名存储在xf_user. 为了比较用户名和密码,您需要SELECT user_id FROM xf_user WHERE username LIKE ...并使用您需要的SELECT data FROM xf_user_authenticate WHERE user_id LIKE ...,然后只需使用password_verify();将经过清理的用户输入与存储在数据库中的散列密码进行比较。请注意,散列密码与用于散列它们的成本和盐值一起存储在 .bin blob 中,这些是 的默认值password_verify();,因此在比较之前您真正需要做的就是剥离其余的使用$password = substr($password, 22, -3);($password是来自数据库的字符串),因为散列密码在 22 个字符后开始,末尾有 3 个尾随字符,散列长度为 60 个字符,总 blob 字符数为 85。
我最近还负责开发一个登录验证系统,该系统将与在论坛注册页面上创建的用户帐户一起使用。通过这种方式,您可以将具有正确数据库连接信息的这些脚本附加到任何外部网站,即使在不同的服务器上(假设您没有使用共享主机),并根据论坛帐户信息成功验证用户登录请求。从那里您可以毫无问题地提取个人资料信息或帐户头像,甚至他们的帖子历史记录!
这是我想出的:
首先,显而易见的。设置数据库连接:
<?
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());
?>
现在我还选择使用函数并将它们与登录表单分开存储,因此当用户提交时,functions.php 包含在登录中。
这是我的功能:
<?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;
}
从那里,我的登录脚本如下所示:
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);
}