查询产生意外结果(SHA1)

6

我有一个用于更新用户数据的表单。它提交到这个页面:

<?php
    //Update user table
    session_start();
    include 'sql_connect_R.inc.php';

    $id = mysql_real_escape_string($_POST['userID']);
    $password = mysql_real_escape_string($_POST['user_passwrd']);

    $salt = time();
    $hash = sha1($password . $salt);

    mysql_query("UPDATE users SET user_passwrd = '$hash', stamp = '$salt', pending = 'yes'
    WHERE userID = '$id'");

    mysql_close($con);
?>

我相信发生的情况是当"stamp"字段用$salt填充时,与计算$hash时得到的值不同。因此,当用户在这里进行签名并进行检查时:

$qry="SELECT * FROM users WHERE userlogin = '$login' AND user_passwrd = sha1(CONCAT('$password', stamp))";
    $result=mysql_query($qry);
    $row = mysql_fetch_assoc($result);
    $num = mysql_num_rows($result);

当我输出 $num 时,它返回一个值为0的结果。我想知道是否有一种方法可以确保 $salt 的值在被用于 $hash 和更新 'stamp' 字段时保持不变。能否有人帮助我或指点我正确的方向?谢谢。


检查一下是 PHP 插入了错误的哈希值还是 MYSQL 寻找了错误的哈希值。这样可以将问题空间减半。 - David Schwartz
错误的哈希值被插入了。我认为在密码被哈希化时$salt的值与插入数据库时的$salt值之间存在差异,但我不是很确定。 - Spud
user_passwrd 的列定义是什么? - Ben
第二段代码中的$password是什么? - Vincent Savard
感谢所有的评论。我想报告一下,我已经“解决”了这个问题。有一天晚上我更改了密码输入字段的名称,但忘记更改$_POST值。当然,这样做没有向$hash提供$password值。虽然我为此感到尴尬,但我认为分享我的疏忽非常重要,以示例说明检查所有可能出现错误的地方是多么重要。我没有仔细检查所有内容,并对问题性质做出了错误的假设。干杯! - Spud
显示剩余4条评论
3个回答

1

更多的想法,所以我把我的评论改成了一个答案...

值得注意的是,当存储时你使用了 PHP 的 SHA1 函数,但在检索时使用了 mysql 的函数。它们应该是相同的,但这是我首先要调试的地方。尝试使用 mysql 的 sha 函数来存储哈希值或根据登录信息检索记录,读取盐并在 PHP 中进行比较。

你是如何存储时间戳的?有可能它被转换/舍入/裁剪/以某种方式作为日期字符串处理吗?只是为了做个健全性检查,在两个步骤中都取出你输入到 sha1 函数中的字符串,并检查它们是否相同。

除了你的评论之外,你能否发布表中相关字段的架构?


user_passwrd varchar(60) No /
stamp int(50) No ... $salt的值在密码被哈希和插入“stamp”字段之间可能不同吗?
- Spud
如果您直接调用time()两次,那么它就不应该出现问题,但是在此之后将其存储在变量中,它只是一个数字。尝试在mysql INSERT之后输出$salt,然后将其与存储在数据库中的值进行比较。 - Basic
我检查过了,在更新函数之前和之后都是一样的。现在我真的很困惑。 - Spud
尝试在PHP和MySQL中执行SHA1("Test") - 你得到了相同的结果吗? - Basic
感谢所有的评论。我想报告一下,我已经“解决”了这个问题。有一个晚上我更改了密码输入字段的名称,却忘记了更改 $_POST 值。这当然没有向哈希提供 $password 的值。虽然我对此感到很尴尬,但我认为分享我的疏忽非常重要,以说明检查错误可能出现的所有地方是多么重要。我没有仔细检查一切,并对问题的性质作出了错误的假设。干杯 - Spud
@Spud 我们都犯过这种错误,所以不要太担心,感谢你抽出时间来告诉我们 :) - Basic

0

感谢所有的评论。我想报告一下,我已经“解决”了这个问题。有一天晚上我更改了密码输入字段的名称,但忘记更改$_POST值。当然,这样做没有向$hash提供$password值。虽然我为此感到尴尬,但我认为分享我的疏忽非常重要,以示例说明检查所有可能出现错误的地方是多么重要。我没有仔细检查所有内容,并对问题性质做出了错误的假设。代码运行良好,问题出在键盘前面的松脱螺丝上。干杯!


-1

你的查询方式不正确。你需要在字符串中连接变量,而不是使用单引号。使用位于1键左侧的引号 ``。这是大多数MySQL读取查询的方式。例如:

<?php
      //Update user table      
session_start();      
include 'sql_connect_R.inc.php';        
$id = mysql_real_escape_string($_POST['userID']);      
$password = mysql_real_escape_string($_POST['user_passwrd']);        
$salt = time();      
$hash = sha1($password . $salt);        
mysql_query("UPDATE `users` SET `user_passwrd` = '".$hash."', `stamp` = '".$salt."', `pending` = 'yes' WHERE `userID` = '".$id."'");        
mysql_close($con);  
?> 

$qry="SELECT * FROM `users` WHERE `userlogin` = '".$login."' AND `user_passwrd` = '".sha1(CONCAT($password, stamp))".'";        
$result=mysql_query($qry);        
$row = mysql_fetch_assoc($result);        
$num = mysql_num_rows($result); 

这个小改动应该会有所帮助。有时候数据库可能会有些敏感。希望这能有所帮助。

这是不正确的。反引号绝对不是必需的(其实,我甚至建议不要使用它们),而且当您使用双引号时无需进行连接。 - Vincent Savard
过去,这种方法对我有帮助。我不完全确定为什么,但是当我将其更改为反引号并连接变量时,一切都正常工作。因此,我已经这样做了一段时间。谁说这不会帮助他呢?我没有看到你回答这个问题。我只是想帮忙。 - jpferrierjr
1
当然你也许已经知道,但你必须知道你在做什么。我并不是要抨击你。反引号的目的基本上是为了"转义"列、表或数据库名称。这允许您在结构名称中使用特殊字符,例如空格,或者使用保留关键字。显式连接在这种情况下将无效,因为它与 OP 的代码执行的是完全相同的操作。查询本身正常工作,问题在于数据不正确。(1) - Vincent Savard
如果我没有给出答案,那很可能是因为那些问题超出了我的掌控范围。我无法测试 OP 的代码,也无法测试他的数据。我完全依赖于他做我可能要求他做的任何任务,而这不是我喜欢做的事情。(2) - Vincent Savard
感谢所有的评论。我想报告一下,我已经“解决”了这个问题。有一天晚上我更改了密码输入字段的名称,但忘记更改$_POST值。当然,这样做没有向$hash提供$password值。虽然我为此感到尴尬,但我认为分享我的疏忽非常重要,以示例说明检查所有可能出现错误的地方是多么重要。我没有仔细检查所有内容,并对问题性质做出了错误的假设。干杯。 - Spud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接