我正在尝试创建一个登录表单。这是我的HTML表单代码
<html>
<head>
<title>Login</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="container login">
<form action="login.php" method="post" class="form-signin" id = "login_form" >
<h2 class="form-signin-heading">User Login</h2>
<input type="text" name="username" size="20" placeholder="Username">
<input type="password" name="password" size="20" placeholder="Password"></br>
<input type="submit" value="Log In" class="btn btn-large btn-primary">
<a href="signup.html">Sign Up</a>
</form>
</div>
</body>
</html>
<?php
}
?>
这是我的PHP代码
<?php
if (isset($_POST) && !empty($_POST)) {
session_start();
//connecting to the database
include("config.php");
//Storing username in $username variable.
$username = mysql_real_escape_string(stripslashes($_POST['username']));
//Storing password in $password variable.
$password = mysql_real_escape_string(stripslashes(md5($_POST['password'])));
$match = "SELECT id FROM $table WHERE username = '" . $username . "' and password'" . $password . "';";
$qry = mysql_query($match);
$num_rows = mysql_num_rows($qry);
if ($num_rows <= 0) {
echo "Sorry, there is no username $username with the specified password.";
echo "Try again";
exit;
} else {
$_SESSION['user'] = $_POST["username"];
header("location:index.html"); // Page to redirect user after login.
}
} //else{}
?>
我已将'mark99'用户名和'1234'密码插入数据库,但它不断给出错误,说明用户名不存在。有什么想法吗?
答案 0 :(得分:1)
只是为了headstuff(所以你已经知道为什么Fred -ii-说不使用这个代码) - 我会把它分开,按顺序,我经历过它(这不是对提出这个问题的人的个人挖掘 - 但只是想知道试图在LAMP堆栈上构建一个中途安全的应用程序需要一点点关心和预见......和血腥的玩世不恭相结合,假设人类最坏的人帮助):
第1点
不是很大 - 但是如果你要开始一个会话,你应该开始一个会话而不管是否有$_POST
数据。您可能需要配置文件并在其他任何地方之前在顶部启动会话。
不是终端错误(因为您没有会话验证) - 只是很奇怪。
第2点
您已在此文件(echo
)中获得输出,因此它必须位于文档根目录下并且可在网络树中使用。
include("config.php");
这不是真正写好的,应该是require_once 'config.php';
(假设它是必需的程序文件,而不是可以允许失败的可选包含)但是那个&#39 ; s 不是错误。错误是您在文档根目录中获得了配置文件。理论上,该文件中的服务器配置错误或简单错误可能允许该文件的内容以纯文本形式输出到屏幕,可能会向world + dog显示您的数据库连接字符串(以及谁知道还有什么)。
配置文件应该存在于Web树之外,或者在失败的情况下,存在于受.htaccess
Deny from all
保护的目录中。永远不能通过HTTP访问它们。
第3点
mysql
库已弃用,根本不应使用; MySQLi或PDO是最佳选择,理想情况下是绑定参数/值:
就个人而言,我得到了PDO。
积分4&amp; 5 强>
$password = mysql_real_escape_string(stripslashes(md5($_POST['password'])));
首先,这个顺序是错误的。您正在哈希$_POST['password']
和然后尝试使用条带 - 一旦它被哈希,就不会有任何斜杠。但是,如果您试图阻止人们在密码中使用斜杠(或其他),则需要在散列字符串之前将其删除。
下一个md5
不应该被用作密码哈希算法,它被发现是弱的,并且可能比它应该更频繁地强制创建字符串冲突。
是的,应仅存储哈希值或&#34;指纹&#34;密码本身而不是密码本身,但理想情况下,您希望对这些密码进行加密和哈希(至少sha1
),而不是简单地将它们放入md5()
函数中。
请参阅:http://uk3.php.net/mcrypt例如
搜索&#34;密码salting散列&#34;使用您选择的搜索引擎。
第6点
SELECT id FROM $table
WHERE username = '" . $username . "'
and password = '" . $password . "';
我在=
中添加了原始问题中遗漏的内容,但仍然在您的查询中与用户名和密码不匹配 ...如果有人设法在您的用户名中输入SQL注入,永远不会检查密码。想象:
SELECT user.id
FROM user WHERE user.username = 'fred' OR 1 = 1
-- AND user.password = 'abc123'
最好从数据库中选择用户ID和密码指纹,然后在应用程序中评估密码,而不是信任数据库层中的密码检查。这也意味着您可以在应用程序本身中使用专用的散列和腌制算法来验证您的密码。
第7点
$_SESSION['user'] = $_POST["username"];
这只是在会话中存储用户名?这绝不应该用作&#34;登录验证程序&#34;特别是在你的会话中没有任何东西(显然)没有阻止hijacking。
会话ID可以很容易地从实时会话的cookie中嗅到,并且所需要的只是&#34;借用&#34;别人的登录。您至少应该尝试通过关联用户的IP地址,UserAgent字符串或您可以在每个页面上比较的相对静态数据的其他组合来减少会话被劫持的可能性......存在缺陷几乎任何方法(特别是,如果你发现,如果你有访问者使用AOL) - 但你可以制作一个可能达到99%以上的有效会话指纹,以减少劫持,用户几乎没有机会&# 39;会话被错误地倾倒。
理想情况下,当用户需要执行“特权”时,您可能还需要为会话创建令牌以缓解CSRF攻击。对数据库的操作(更新他们的详细信息或其他)。当用户登录时,令牌可以是存储在数据库和/或SSL cookie中的完全随机且唯一的代码(假设用户不能执行任何在HTTPS之外更新数据库的操作,因为它只会传输互联网上的明文数据 - 这将是一个坏主意。)
将令牌放入任何/所有表单的隐藏表单字段中,并在提交表单时检查存储在cookie(或会话或数据库)中的值。这样可以确保提交表单的人至少在您的网站上有一个实时会话。
答案 1 :(得分:-1)
你说你在表格中插入了 1234 作为密码吗?
并在
$password = mysql_real_escape_string(stripslashes(md5($_POST['password'])));
你输入的密码意味着在$ password变量中它不再是1234,这就是它给出错误的原因。
删除 md5()或在表格中插入md5值1234
答案 2 :(得分:-1)
可能会有一些问题造成这种情况。
你的$ match语句中的首先你缺少一个等于运算符的密码:
这:
$match = "SELECT id FROM $table WHERE username = '".$username."' and password'".$password."';";
应该是这样的:
$match = "SELECT id FROM $table WHERE username = '".$username."' and password = '".$password."';";
其次您是否在使用md5 对其进行哈希处理后将密码插入数据库?
如果没有,则您的查询尝试将md5(密码)与密码匹配。