目标
从XML"数据库"中获取数据,这是一种验证登录数据的简单(我知道,非常不安全)的方法。
此处的代码负责数据库和检索值。 选项一是我最初尝试的方法,因此它仍然包含将用户名和密码的输入数据与XML数据库中的数据交叉引用的代码。
选项二是我尝试另一种方法的地方。 似乎都没有工作。
截图。
选项一:
login.php:
if( !isset($_SESSION['user']) ) { ?>
Please login to view your message log, and see whether anyone has left you a message.
$passwordValid = $_GET['error'];
if( $passwordValid == 1 ) {
echo"Falsches Password";
};
?>
authenticate.php:
session_start();
// Load Credential Database
$xml = new DOMDocument();
$xml->load('../logins.xml');
$xpath = new DOMXPath($xml);
// Variable Declarations
$user = $_POST['Username'];
$password = $_POST['Password'];
// XPath Query for Correct Credential
$queryUsers = '//authentication/client/user[. ="' . $user . '"]';
$userActual1 = $xpath->query($queryUsers);
$userActual = $userActual1->nodeValue; // Output: Anton
$passwordActual1 = $userActual1 . 'following-sibling::*[1]';
$passwordActual = $xpath->query($passwordActual1); // Output: damn
// Authentication Checker
if($user == 'Arend' && $password == 'damn') {
$userLogin = true;
$_SESSION['user'] = $user;
header('Location: ../index.php');
} else {
$userLogin = false;
header('Location: ../index.php?error=1');
};
if($userLogin == true) {
header('Location: ../index.php');
};
?>
XML" logins.xml":
Arend
damn
Felipe
damned
Paula
damnest
选项二:
XML代码" test.xml":
damn
damnest
php代码:
$xml = simplexml_load_file('test.xml');
$nodes = $xml->xpath('//authentication/user[@name="Arend"]');
// Variable Declarations
$user ="Arend";
$password ="damn";
echo 'second test' . '';
print_r ($nodes);
echo '';
print_r ($nodes[0]['name']);
echo '';
echo $nodes[0]['name'];
?>
结果:
如您所见,它捕获XML数据和数组以及其结构如何在屏幕快照中进行查看。 我可以获取用户名,但是如果尝试将密码(echo $nodes[0]['password'];)指定为我想要的东西,它将显示下面的第二个图像:
我只是想借此机会指出,这实际上是不安全的,而且实际上完全忽略了您作为系统设计师的职责。 您永远不要保存纯文本密码。 查看bcrypt,尤其是如果您要像这样将它们公开保存时。
同意MiDri。 考虑到他的观点,我认为您的XML并不是最佳格式。 密码节点应该是用户的子节点,或者可能是属性,例如。 asdf或
选项2绝对是不明智的选择(忽略整个logins.xml是一个坏主意),因为它们没有共享的父级。 密码和用户应该以某种方式进行分组。 因此,我想说的是,选择1是唯一值得这样做的选择。
不要存储纯文本密码,请使用password_hash()创建哈希,并使用password_verify()进行验证。
使用DOMXpath::evaluate(),您可以直接获取用户的密码:
$xml = <<
Arend
$2y$10$WjYhm/JoG3Pn.nT7C91cweOCrshRSZOgYFoYvrG8Ry1SS/tohGfA.
Felipe
$2y$10$PlUKayvRmTy61sFMtAhlxePKGAkTL8LU84gvP1EjUn/3e0E2jHMgi
Paula
$2y$10$3XDNia4TqVJ5QlqH/zoX/e9.t7YJF5K1hNVZnnuoslI/hjvv0St1W
XML;
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$passwordHash = $xpath->evaluate(
'string(/authentication/client[user ="Arend"]/password)'
);
var_dump(password_verify('damn', $passwordHash));
输出:
bool(true)
嗯,很方便! 不了解evaluate! 尽管您可以只在查询或simpleXML中使用该XPath并将元素转换为字符串以得到相同的结果。 无论哪种情况,我都希望引起人们的注意,这会阻止$password成为注入向量,但是$name仍需要进行清理。 但是从安全角度来看,您的解决方案仍然更好。 +1
正确,清除或引用值以避免Xpath注入:stackoverflow.com/a/27440520/2265374
这是一个很好的链接。 我可能会更深入地了解。 您认为我们中的任何一个都应该在我们的答案中加上括号吗? 还是只留下功能结果并确认缺陷是什么,而无需解决这些问题?
您承认这是不安全的,因此我不再badge或对此发表评论。
至于使用logins.xml,就像您的第一个示例一样,我有一个合适的XPath及其解决方案。我使用了PHP附带的simpleXML。
//load credentials
$xml = simplexml_load_file(__DIR__.'/logins.xml');
// Variable Declarations
$user = $_POST['Username'];
$password = $_POST['Password'];
$search = $xml->xpath("//authentication/client[./user = '{$user}'][./password = '{$password}']");
if(count($search))
{
//authenticated!
}
else
{
//DENIED
}
它匹配具有子等于$user和等于$password的节点,而不是非或。
count($search)如果不存在,则返回0(false),然后将其他任何类型强制转换为true,这意味着它们存在于您的数据集中。
免责声明,我使用__DIR__是因为测试XPath表达式时XML和PHP对我而言位于同一文件夹中。我想说的是,永远不要在Web根目录或不受HTAccess形式或其他限制保护的地方拥有您的敏感凭据。
为了使用DOMDocument和DOMXPath,它们具有length参数而不是可计数的设置。相反,您可以使用它来检查IF / ELSE
$xmlpath= $xpath->query("//authentication/client[./user = '{$user}'][./password = '{$password}']");
if($xmlpath->length > 0)
{
//authenticate
}
else
{
//not
}
最后一个安全警告是,您使用直接的$_POST变量,并且我想增加对XPath Injection这样的东西的了解,就像SQL注入一样。您的函数不用于显示数据,因此不会从文档中泄漏信息。但是他们可以使用它进行查询,该查询始终返回true并让他们登录。
请参阅示例,包括像您一样的XML登录凭据!:https://www.owasp.org/index.php/XPATH_Injection
第一个解决方案运行良好,非常感谢,我读了有关注入的OWASP页面(这不可避免地导致了有关注入的更多页面),因此,感谢你们俩,我会稍作尝试。