6

我的插件中有一个类似于此的表单:

<!-- Client form -->
<form>
   <?php wp_nonce_field('my_form','_my_token'); ?>
   <!-- Additional form fields -->
</form>

它生成这两个字段:

<input type="hidden" id="_my_token" name="_my_token" value="abcdefghij" />
<input type="hidden" name="_wp_http_referer" value="/wp-admin/tools.php?page=my-plugin%2Fplugin.php" />

当我提交此表单时,我会像这样验证它:

//Server's side check
if(!wp_verify_nonce($_POST['_my_token'],'my_form')){
   echo 'Invalid token! Expected token: '. wp_create_nonce( 'my_form');
   exit;
} 

问题是在服务器上,令牌永远不会改变,它总是一样的,并且在这一步验证总是失败。如果我从 WordPress 注销然后再次登录,客户端令牌已更改,但在服务器上它是相同的。

我已经在本地对此进行了测试,当我再次登录时,它总是会更改双方的令牌,但在我的生产环境中,它只会在客户端更改。

看起来它以某种方式被缓存,但不确定到底是什么。我使用了 WP Super Cache 插件,但它现在被禁用并且这个问题仍然存在。我在生产站点上启用了多站点功能,但我认为这与它无关。有任何想法吗?

4

1 回答 1

1

你期望你的 nonce 改变的时间范围是什么?

在没有其他更改的连续刷新中,页面加载之间的随机数可能相同。基本上,如果您坐在那里并按 F5,您将获得相同的随机数。

这是设计使然。为了使用它们进行验证,需要在短时间内幂等创建随机数。

再一次,基本上,如果这不能以这种方式工作,你将永远无法验证你的 nonce。当您创建它时,值将是一回事,而当您重新创建它以验证它时,值将是另一回事。验证总是会失败。

wp_verify_nonce() 最多可以接受一个随机数(其他条件相同)长达 24 小时(请参阅WP Codex 页面)。您可能需要等待更长的时间才能收到不同的随机数。

可能发生的其他系统事件可能会导致生成新的随机数。我自己从来不需要这样做,但看起来你可以wp_nonce_tick()用来慢跑这个过程。

有可能其中一个或两个wp_create_nonce()(由 直接使用wp_nonce_field())并且wp_verify_nonce()可能已被某些插件重写,因为它们都被定义pluggable.php并打算用于覆盖。一个编写良好的 WP 感知 CDN 或其他缓存解决方案可能正是这样做来保持会话。我不知道超级缓存是否这样做。

或者,如果您的系统配置还没有这样做,您可以选择自己重写这些函数。这将是安全代码,并且要小心编写安全代码:开源安全代码的最大优势在于它是经过同行评审的,并且您的(新)代码可能不会相同。

于 2018-07-30T17:07:58.330 回答