【问题标题】:Drupal form throws error on submissionDrupal 表单在提交时抛出错误
【发布时间】:2014-01-20 20:35:03
【问题描述】:

drupal 表单在提交时会引发以下错误。表单已加载并立即提交,用户在浏览器上并不理想。

'This form is outdated. Reload the page and try again' 

我正在使用具有公共数据库和 Web 服务器(负载平衡器)的两个 drupal 节点,但是当从一个应用程序服务器呈现表单并且提交请求转到另一个应用程序服务器时,似乎会出现上述错误。

我想了解表单令牌存储在哪里,我假设在数据库中。出现上述消息是因为两种情况下的表单令牌不同,并且应用服务器假定请求不是同一会话的一部分。

另外我正在使用 apc 缓存,所以不确定这是否与它有关。

谢谢,

【问题讨论】:

    标签: forms drupal session-variables token


    【解决方案1】:

    令牌存储在 db/form 缓存中,但据我所知,如果您在一台服务器上生成表单,然后提交到另一台服务器,它将使用 php 会话 ID 生成,它将重新生成令牌它使用不同的会话 ID 对其进行检查,因此不会匹配 - 来自 common.inc

    function drupal_get_token($value = '') {
      return drupal_hmac_base64($value, session_id() . drupal_get_private_key() . drupal_get_hash_salt());
    }
    

    您使用什么作为负载平衡器?如果可以,您可能需要考虑启用粘性会话。

    【讨论】:

    • 您好安德鲁,感谢您的回复。当我禁用 APC 缓存时,问题似乎解决了。但是当我只禁用 APC 的 cache_form 时,它不起作用。我的表单是块的一部分。问题是什么会触发这个,因为我虽然会话 ID 将通过数据库共享,当我最初开始访问我的网站时也不会发生这种情况,但是当多个浏览器发出请求时,它会在 APC 缓存开始被填满后引发此错误。
    • 该块是否可能被过度缓存?如果它正在缓存渲染的块,它将在那里有一个陈旧的令牌。你有一个充满表单的缓存块吗?
    • 嘿安德鲁,不知何故,我在数据库和 APC 缓存上的私钥是不同的。这可能是个问题。
    • 你的意思是你的'drupal_private_key'变量有不同的值?如果是这样,那将弄乱令牌,但是不知道最终会如何使用不同的密钥。您是否看过 bootstrap.inc 中的 drupal_random_bytes() - 它似乎使用不同的生成方法,具体取决于可用的方法。您的两台服务器之间是否存在差异导致该值的计算方式不同?感觉好像我开始有点远了,我可能没有想法。
    【解决方案2】:

    我遇到了同样的问题。负载均衡器在两个 Web 节点之间传播流量。 Drupal 会时不时地给我This form is outdated. Reload the page and try again。当表单在一个 Web 节点上生成但提交到另一个 Web 节点时,就会发生该错误。

    我首先查看drupal_validate_form,它(除其他外)根据存储在$form_state['values']['form_token'] 中的表单令牌验证提交的表单。跳转到drupal_valid_token,然后跳转到drupal_get_token。函数drupal_get_hash_salt() 结果在两台服务器上返回不一致的结果。

    由于某种原因,$drupal_hash_salt 仅设置在其中一台服务器上。在未设置的服务器上,Drupal 将根据数据库设置回退以生成盐。

    通过将settings.php 中的$drupal_hash_salt 设置为相同的值解决了该问题。

    【讨论】:

    • 你是怎么设置的?
    • 最后一段是这么说的。设置.php
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-31
    • 1970-01-01
    • 2011-07-28
    • 2014-02-25
    • 2018-11-24
    • 2017-08-24
    相关资源
    最近更新 更多