这里简短而有趣。我可能在这里有些奇怪,但我现在已经失去了几个小时而无法找出问题所在。
我有一个产生nonce的函数,就像这样。它目前并不复杂,但更多的是对我来说是一个新概念的实验。我使用random_bytes作为PHP7 +的mcrypt_create_iv
的自然继承者:
$token = random_bytes(16);
然后将其存储起来:
$session->add('nonce',$token);
(which is essentially....)
$_SESSION[$var] = $val;
同时以我的形式使用,如下所示:
<input name="token" type="hidden" value="<?=$token?>">
表单提交并通过一些验证,依此类推。作为其中的一部分,我检索两个值:
$token = $_POST['token'];
$nonce = $session->get('nonce');
然后我有一个进一步执行的验证点 - 只有在两个值匹配时才进行。问题是,我实际上无法让他们进行验证。这些当前输出都不是真的:
if(hash_equals($nonce, $token))
if($nonce === $token)
var_dump
显示两者都是相同长度的字符串,但由于某种原因,它们不具有可比性。两个值看起来都匹配。
if(hash_equals($nonce, $nonce))
等于true(正如你所期望的那样),所以我只能假设其中一个值在此过程中被改变,可以通过$_POST
或通过我的检索函数(实际上只读取)来自会议)。
我很感激任何有关这方面的帮助/建议 - 我要么忽略了一些显而易见的事情,要么对此缺乏经验。
答案 0 :(得分:3)
并非所有随机字节值都直接在HTML中有效。如果字符串包含ascii字母和数字([0-9a-zA-z]
)的常规序列之外的值,则任何事情都可能发生,如果您不为HTML上下文转义它。如有必要,您可以使用htmlspecialchars
来转义值,或者使用随机字节的散列或base64编码版本。
一个很好的例子是,如果"
的ascii值包含在16个随机字节中,那么HTML属性将提前结束。 HTML并不非常喜欢控制序列(低ascii字符)或当前编码之外的字母(如果是UTF-8,则在跨多个字节查看时,任何高于127的值都需要是有效的UTF-8代码点)。