通过get、url中的php和安全性传输数据

通过get、url中的php和安全性传输数据,php,mysql,Php,Mysql,这是第一个问题,我需要你的帮助 我使用php中的header location方法将表单数据从第一页传输到第二页 在第二页上,我使用get接受数据 现在这里是第二页的url,在发送数据后(即提交表单) 当用户位于第二页时,第二页上的数据将根据mysql数据库中的id号显示 现在的问题是,当用户在第二页时,他更改了数字(例如123改为78),显示数据库中id=78的数据,这是不好的 我怎样才能阻止它 请注意:我不能使用post,也不能使用会话 伊迪特: 第一页上的php代码,要转移到第二页: /

这是第一个问题,我需要你的帮助

我使用php中的header location方法将表单数据从第一页传输到第二页

在第二页上,我使用get接受数据

现在这里是第二页的url,在发送数据后(即提交表单)

当用户位于第二页时,第二页上的数据将根据mysql数据库中的id号显示

现在的问题是,当用户在第二页时,他更改了数字(例如123改为78),显示数据库中id=78的数据,这是不好的

我怎样才能阻止它

请注意:我不能使用post,也不能使用会话

伊迪特:

第一页上的php代码,要转移到第二页:

// after all validations are okay
$insert = //insert into database
$result = mysql_query($insert);
if($result)
{
echo("<br>Input data is succeed");
$lastInsertedId =  mysql_insert_id();
header('Location:form1_conf.php?id='.$lastInsertedId); //THIS IS THE IMPORTANT LINE
}
else
{
$message = "The data cannot be inserted.";
$message .= "<br />" . mysql_error();
}
//在所有验证都正常之后
$insert=//插入数据库
$result=mysql\u查询($insert);
如果($结果)
{
回波(
输入数据成功); $lastInsertedId=mysql\u insert\u id(); header('Location:form1_conf.php?id='。$lastinertedid);//这是重要的一行 } 其他的 { $message=“无法插入数据。”; $message.=“
”.mysql_error(); }
您永远不应该信任url,因为总会有办法操纵数据

因此,您应该在检索数据之后进行验证。如果结果不适合您:例如,ID=1的loggedin用户从userid=3请求设置页面,则不显示结果

<?php
    $userID = $_GET['id'];
    if($userID != $expectedResult)
    {
        //show errormessage, redirect or show the page with the users data
    }

?>

您需要跟踪用户及其在数据库中的id,以确保他们没有更改号码。因此,当您通过
get
获取信息时,请确保信息是合法的


用户可以更改id,甚至尝试通过url直接进入该页面。因此,您需要某种服务器端检查来验证它是否正常。

您的问题不在于URL:对于超级用户来说,更改cookie或POST变量与为普通用户编辑GET变量一样简单。您需要某种方式将请求“签名”为有效

最简单的方法是使用“预共享密钥”,您可以使用单向散列来验证请求

重定向器:

$newURL = '/newpage?id='.$id.'&hash='.sha1('mypresharedkey'.$id);
header('HTTP/1.1 303 See other');
header('Location: '.$newURL);
die;
另一页:

$idToShow = $_GET['id'];
$hash = sha1('mypresharedkey'.$id);
if($hash != $_GET['hash'])
  die("Tssss, don't play with the address bar!");
else
  RenderThePage();
这确保了最终用户只能访问提交允许他们访问的页面


对于您的特定代码:

...all prior code
$lastInsertedId = mysql_insert_id();
$timestamp = time();
header('Location:form1_conf.php?'.http_build_query([
      'id' => $lastInsertedId,
      'time' => $timestamp,
      'hash' => sha1('some-generated-key'.$timestamp.$lastInsertedId)
]);
在另一个页面中,如果您愿意,包括一个定时炸弹(否则只需将其注释掉):

如果你不直接传递身份证号码,但以某种方式对其进行加密,你可能会使这种“作弊”变得复杂一些

比方说,你定义了一种盐:

define(SALT, 'long weird salt with special characters etc.');
下面是您想要的第一部分:

$lastInsertedId = mysql_insert_id();

$querytag = base64_encode($lastInsertedId); // just to make it less readable
$checksum = md5($querytag . SALT); // and make a hash

header('Location:form1_conf.php?id=' . $querytag . '&checksum=' . $checksum); 
在form1_conf.php的开头,您将:

$encodedId = $_GET['id'];
$oldChecksum = $_GET['checksum'];

$newChecksum = md5($encodedId . SALT);

$id = base64_decode($encodedId);

if($newChecksum != $oldChecksum) {
    die('You Are Cheating!');
}

... do something with the $id ...
关键是,由于您向散列添加了盐,一些用户不能简单地在更改的ID上使用md5,因为他缺少您使用的盐


如果每次的盐不是一样的话,那就更好了。

你无法控制用户发送的数字。一个帖子可以被轻易伪造。您唯一的选择是使用服务器端存储来保留该数字,例如会话、数据库、驱动器上的文件等。“我不能使用POST,也不能使用会话”并祈祷,为什么不?GET是不安全的。句号。没有真正的方法来确保url中的数据没有被弄乱。你可以用数字将文件写入磁盘,对客户端的IP、timestamt和问题中的数字使用哈希,但基本上,你只会让它变得更难yourself@EliasVanOotegem胡说,读我的答案。只要用散列签名,URL就不会受到任何篡改。这正是银行API、PayPal等的工作方式。@NielsKeurentjes:注意你的语言。。。此外,尽管不太可能,哈希冲突从来都不是100%不可能的。因此,即使您的
sha1
hash也不是100%安全的,只有99.999999…%。另外:比较散列时,
$id
分配了什么?客户端可能已发送id为123或id=12的有效请求。如果get var id为常量,则不需要uri参数SHA1为160位,因此146150163330902919182036848327163E+48选项。这使得它大约99.99999999999999999999999999999999999999999999999999999999999999999%不会发生意外碰撞。至于验证——我假设回发验证客户端可以访问ID123。因此,对123的请求是可重复、可缓存和可存储的。如果不是这样的话,那么在参数中添加时间戳,在定时炸弹中添加哈希,URL的有效性就微不足道了。他不能使用会话。我没有看到这一点。Thx的提示。这似乎是一个完美的解决方案,但为了实现它,我需要更多的帮助。。请在这里多呆一会儿,让我分析一下情况,我想问更多的问题。@neo我做了一个类似的东西,也许更容易使用。请检查问题中的编辑。。搜索这些单词。请告诉我如何将您的解决方案应用到该行?寻找有这些数据的线,这是重要的线哇。我爱你,伙计。顺便说一句我在哪里可以找到学习和实现这个“一些生成的密钥”的链接?它只是一个,一个密码学的基本概念,也称为预共享密钥或PSK。你可以用一个生成的密码替换它,或者随机敲击你的键盘,直到它达到50个字符或更多-只要两个页面使用相同的PSK,这就行了。朋友,请检查更新的问题,我添加了php代码来传输第一页的值。此外,id不仅仅是这个,它是由服务器生成并自动递增的。。我如何在那里实施您的解决方案?
$encodedId = $_GET['id'];
$oldChecksum = $_GET['checksum'];

$newChecksum = md5($encodedId . SALT);

$id = base64_decode($encodedId);

if($newChecksum != $oldChecksum) {
    die('You Are Cheating!');
}

... do something with the $id ...