【问题标题】:CodeIgniter CSRF protection and page cachingCodeIgniter CSRF 保护和页面缓存
【发布时间】:2013-02-13 18:29:16
【问题描述】:

我已经四处搜索,但找不到任何关于此的信息。我是唯一一个体验过 CodeIgniter 中的 CSRF 保护不适用于页面缓存的人吗?

我有什么:

将通过此行缓存的网页:

$this->output->cache( 120 );

在该页面上的 Javascript 中,我有一个 Ajax 调用,其中数据也包含 CSRF 令牌。禁用缓存或禁用 CSRF 保护时一切正常。

是否有人知道解决方法或其他方法,以便我可以启用缓存和 CSRF 保护?

谢谢!

【问题讨论】:

  • 当 CSRF 与 AJAX 页面缓存配对时,什么究竟不能正常工作?您能否展示更多代码(例如您的 ajax 调用)以及您是如何生成表单的(我假设使用 form_open())?
  • 页面缓存也会缓存表单中的 csrf 令牌,因此在 csrf 失败的情况下不会刷新。
  • 我问是因为我假设form_open() 会为您处理这个问题,就像基准测试 (ellislab.com/codeigniter/user-guide/general/caching.html) 一样。
  • 是的,我正在使用 form_open(),但 CodeIgniter 的处理方式与基准测试不同。

标签: codeigniter caching csrf


【解决方案1】:

我有点惊讶form_open() 没有为你处理这个问题,就像没有缓存基准测试函数的输出一样。

这里有两种可能的解决方法。

使用缓存驱动程序 (!= output->cache())

您可以使用caching driver's key-value cache 来保存已渲染的页面部分,而不是使用缓存完全呈现的页面的输出类缓存。

如果包含这个有问题的 CSRF 令牌的表单很复杂并且包含来自外部数据源的大量动态内容,请缓存这些数据库结果(使用缓存驱动程序或通过启用 database result caching)并将缓存的值输入到动态形式。

手册中关于基于文件的缓存的警告:

与输出类的缓存不同,基于驱动程序文件的缓存 允许缓存视图文件。小心使用它,并且 确保对您的应用程序进行基准测试,因为一个点可能会出现在哪里 磁盘 I/O 将抵消缓存带来的积极收益。

当然,如果您可以访问 memcached 或 APC,请改用它。

禁用该页面和配置文件的输出缓存。

拦截输出缓存(全渲染页面)并替换 CSRF 令牌值

我在Caching forms with CSRF tokens(在 Symfony 中)遇到了一个有趣的解决方案。套用原作者:

  1. 在设置缓存响应之前,查找并替换 CSRF 令牌。
  2. 将标记的位置与响应一起存储(因此它也会被缓存)。
  3. 在从缓存返回响应之前注入新的 CSRF 令牌。

在 CodeIgniter 中,拦截缓存 seems to require 使用 the pre_system hook-point,尽管在您的情况下,您可能可以使用 cache_override。看看at this excellent article CodeIgniter 实现 CRSF 令牌的方式以获得灵感。不过,我认为实施起来并不容易。

不要缓存那个页面也不要担心

这显然是最简单的解决方案。测试一下。根据您的页面复杂性,不缓存该页面子集的负面性能影响可能远远超过实现上述两种解决方案中的任何一种的痛苦。 (由于我们不知道您的视图或控制器的外观,因此在您的情况下这是否是可接受的解决方案并不是很明显)。如果是isolated login form in an SPA,你可能就可以不用了。

【讨论】:

  • 非常有帮助的答案!我会深入研究,让你知道我的选择和解决方案。
  • @Roy 谢谢!研究这个答案,我发现这实际上是一个覆盖面有点差的话题。它促使我制作了一个示例 CI 站点来试验不同的缓存方法(完成后的博客 + github)。也请告诉我们您的决定!
  • 我认为最好的解决方案是扩展输出类。如果你看这里:github.com/EllisLab/CodeIgniter/blob/master/system/core/… 你会发现经过的时间和内存使用情况。通过在此之后添加某种搜索和替换,例如:搜索名称等于 $CI->security->get_csrf_token_name() 的隐藏输入并将值替换为 $CI->security->get_csrf_hash()。这样就行了!
  • 干得好,@Roy!感谢您回来发布您的发现。
  • 尚未实现,但我认为这是最好的解决方案。同时,我已将此作为问题发布,但他们不认为这是一个问题:github.com/EllisLab/CodeIgniter/issues/2325。当我实现它时,我会发布代码!
猜你喜欢
  • 1970-01-01
  • 2013-08-25
  • 2013-09-20
  • 2012-02-03
  • 2017-06-14
  • 2011-10-23
  • 1970-01-01
  • 2017-02-10
  • 2016-01-15
相关资源
最近更新 更多