PHP认证脚本

发布于 2024-08-04 03:21:29 字数 507 浏览 0 评论 0原文

我需要完成以下身份验证脚本。我在 php/pdo 方面很弱,所以我不知道如何询问等于 1 的行数,然后根据查询结果设置会话 ID。我不仅需要从结果中设置 $_SESSION['userid'],还需要设置 ['company'] 和 ['security_id'] 。

这是我所拥有的:

$userid   = $_POST['userid'];
$password = $_POST['pass'];
if ( $userid != "" || $password != "" )
{
  $sql = "SELECT * FROM contractors WHERE userid = '" . $userid . "' AND password = '" . $password . "'";
  $result = $dbh->query( $sql );
} else
{
  echo "login failed. Your fingers are too big";
}

可选信息: 浏览器:火狐

I need the following authentication script finished. I am weak at php/pdo so I do not know how to ask for the number of rows equalling one and then setting the session id's from the results of the query. I need to not only set the $_SESSION['userid'] but also the ['company'] and the ['security_id'] as well from the results.

here is what I have:

$userid   = $_POST['userid'];
$password = $_POST['pass'];
if ( $userid != "" || $password != "" )
{
  $sql = "SELECT * FROM contractors WHERE userid = '" . $userid . "' AND password = '" . $password . "'";
  $result = $dbh->query( $sql );
} else
{
  echo "login failed. Your fingers are too big";
}

Optional Information:
Browser: Firefox

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清风无影 2024-08-11 03:21:29

永远不要使用该代码!

那里存在非常严重的 SQL 注入。您获取的每个用户输入,无论是来自 cookie 还是 CGI,或者无论,在用于 SQL 语句之前都必须进行清理。我可以通过尝试使用如下用户名登录来轻松闯入该系统:

user'; UPDATE contractors SET password = '1337'

...之后我就可以以任何人的身份登录。抱歉,如果我听起来很激进,但该代码的作用就像忘记锁上您公司的前门,而该公司可能甚至不包含警报系统。

请注意,输入是否实际上来自用户并不重要(也许它是预先填充的、隐藏的)。从安全角度来看,来自外部任何地方的任何内容都必须被视为包含用户的恶意输入。

据我所知,您需要使用 quote< /a> PDO 的功能来正确清理字符串。 (在 mysql 中,这可以使用 mysql_real_escape_string() 来完成。)我不是 PDO 方面的专家,请注意,如果我在这里错了,请有人纠正。

此外,您可能不应该直接在数据库中存储任何密码,而是使用哈希函数创建屏蔽密码,然后根据用户提供的密码创建哈希,并匹配哈希。您可以使用 PHP hash 函数来执行此操作。

至于其他问题,我不知道你对 SQL SELECT 的方法是否是最好的方法。我只需选择相应用户的密码并尝试在程序中进行匹配。我不认为您使用的方法有任何错误,但它看起来不合逻辑,因此更有可能错过一些错误 - 在这种情况下密码和登录名会创建一个漏洞利用窗口。

要按照您的方式进行操作,您需要注意从 PDO 查询 是一个PDOStatement,似乎没有可靠的函数来直接计算结果行数。您需要使用的是 fetchAll 它返回行数组,并对其进行计数。然而,正如我所说,这对我来说就像是容易失败,所以我觉得检查代码中的密码会更安全。在这样一个安全关键的地方,按照我的口味,与实际的密码匹配同情心相差太大。

因此,要获取用户 ID 的密码,您可以使用 PDOStatement 的 fetch () 从结果中返回列的内容。例如,使用 PDO::FETCH_ASSOC 根据列名称将它们放入关联数组中。

以下是修复它的方法:

$userid_dirty   = $_POST['userid'];
$password_dirty = $_POST['pass'];
$success = false; // This is to make it more clear what the result is at the end
if ($userid != "" || $password != "") {
  $userid = $dbh->quote($userid_dirty);
  $passwordhash = hash('sha256',$password_dirty);
  $sql = "SELECT userid, passwordhash, company, security_id FROM contractors WHERE userid = ".$userid;
  $result = $dbh->query( $sql );
  if ($result) { // Check if result not empty, that userid exists
    $result_array = $result->fetch(PDO::FETCH_ASSOC);
    if ($result_array['PASSWORDHASH'] == $passwordhash) {
       // login success
       $success = true;

       // do all the login stuff here...
       // such as saving $result_array['USERID'], $result_array['COMPANY'], $result_array['SECURITY_ID'] etc. 

    } // else fail, wrong password
  } // else fail, no such user
} else {
  // fail, userid or password missing
  echo ' please enter user id and password.';
}
if (!$success) {
  echo ' login failed.';
}

当然,代码可以稍微清理一下,但这应该解释需要做什么。请注意,由于密码均经过哈希处理,并且从未在 SQL 中使用,因此实际上不需要清理。但我把它留在那里以防万一,因为在原始代码中它是在查询中使用的。

请注意,所有有关存储密码的代码都需要更改以存储哈希值而不是密码。另外,最好在密码中添加 salt在散列之前。

另外,我提供代码只是为了教育目的 - 我只是认为代码是解释如何执行此操作的最清晰方式。所以不要误认为这个网站是一个请求代码的服务。 :)

DO NOT EVER USE THAT CODE!

You have a very serious SQL injection open there. Every user input that you take, whether from cookies or CGI, or wherever, must be sanitized before it's used in an SQL statement. I could easily break into that system by attempting a login with an username like:

user'; UPDATE contractors SET password = '1337'

... after which I could then login as anyone. Sorry if I sound aggressive, but what that code does is like forgetting to lock the front door into your company which probably doesn't even contain an alarm system.

Note that it doesn't matter whether the input is actually coming from the user or not (perhaps it's in a pre-filled, hidden from). From the security point of view, anything that comes from anywhere outside has to be considered to contain malicious input by the user.

As far as I know, you need to use the quote function of PDO to properly sanitize the string. (In mysql, this would be done with mysql_real_escape_string().) I'm not an expert on PDO, mind you, somebody please correct if I'm wrong here.

Also you probably shouldn't store any passwords directly in the database, but rather use a hash function to create a masked password, then also create a hash from the user provided password, and match the hashes. You can use the PHP hash function to do this.

As for other issues, I don't know if the approach you have on SQL SELECT is the best approach. I would just select the corresponding user's password and try matching that in the program. I don't think there's any fault in the method you're using either, but it just doesn't seem as logical, and thus there's a greater chance of me missing some bug - which in case of passwords and logins would create a window for exploits.

To do it your way, you need to notice that the result you are getting from the PDO query is a PDOStatement, that doesn't seem to have a reliable function to diretly count the amount of result rows. What you need to use is fetchAll which returns an array of the rows, and count that. However, as I said this all feels to me like it's open for failures, so I'd feel safer checking the password in the code. There's just too much distance from the actual password matching compasion for my taste, in such a security-critical place.

So, to the get the resulting password for the userid, you can use PDOStatement's fetch() which returns the contents of the column from the result. Use for example PDO::FETCH_ASSOC to get them in an associative array based on the column names.

Here's how to fix it:

$userid_dirty   = $_POST['userid'];
$password_dirty = $_POST['pass'];
$success = false; // This is to make it more clear what the result is at the end
if ($userid != "" || $password != "") {
  $userid = $dbh->quote($userid_dirty);
  $passwordhash = hash('sha256',$password_dirty);
  $sql = "SELECT userid, passwordhash, company, security_id FROM contractors WHERE userid = ".$userid;
  $result = $dbh->query( $sql );
  if ($result) { // Check if result not empty, that userid exists
    $result_array = $result->fetch(PDO::FETCH_ASSOC);
    if ($result_array['PASSWORDHASH'] == $passwordhash) {
       // login success
       $success = true;

       // do all the login stuff here...
       // such as saving $result_array['USERID'], $result_array['COMPANY'], $result_array['SECURITY_ID'] etc. 

    } // else fail, wrong password
  } // else fail, no such user
} else {
  // fail, userid or password missing
  echo ' please enter user id and password.';
}
if (!$success) {
  echo ' login failed.';
}

Of course, the code can be cleaned up a bit, but that should explain what needs to be done. Note that since the password is both hashed, and never used in the SQL, it doesn't actually need cleaning. But I left it there just in case, since in the original code it was used in the query.

Note that all the code concerning storing passwords need to be changed to store the hash instead of the password. Also, it would be a very good idea to use a salt added to the password before hashing.

Also, I provided the code simply for educational purposes - I just thought that code was the clearest way to explain how to do this. So do not mistake this site as a service to request code. :)

梦回梦里 2024-08-11 03:21:29

php 手册是学习 PHP 的绝佳资源。看起来你懂一点 SQL,并且听说过 PDO,这是一个好的开始。如果您在 google 上搜索“PDO”,或者在 PHP 手册中查找该术语,您将找到 PDO 部分手册的。看起来您已经找到了 ->query 函数,所以现在您需要查看它返回的内容。转到该函数的手册页,我们看到它返回一个PDOStatement 对象。 PDOStatement 一词有助于链接到手册中的相关页面,其中列出了该对象上可用的方法。有一个 rowCount() 方法可能会执行您想要的操作。

The php manual is an excellent resource for learning PHP. It looks like you know a little SQL, and you have heard of PDO, which is a good start. If you search google for "PDO", or look in the PHP manual for the term, you'll find the PDO section of the manual. It looks like you've found the ->query function, so now you need to see what that returns. Going to the that function's manual page, we see that it returns a PDOStatement object. The word PDOStatement is helpfully linked to the relevant page in the manual, which lists the methods available on that object. There is a rowCount() method that will likely do what you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文