我在测试使用 Play 的 CSRF 保护的 Controller 时遇到了一些问题。为了证明这一点,我创建了一个非常简单的 Play 应用程序,它以最低限度地展示了这个问题。
https://github.com/adamnfish/csrftest
完整的细节在该存储库的自述文件中,但在这里总结一下:
考虑一个设计用于处理表单提交的 Controller 。它有一个使用 CSRFAddToken 的 GET 方法和一个使用 CSRFCheck 的 POST 方法。前者将 CSRF token 添加到请求中,以便可以将表单字段放入呈现的 View 中,其中包含有效 token 。提交该表单时,如果 CSRF 检查通过并且提交有效,则会发生其他事情(通常是重定向)。如果表单提交无效,将重新显示表单提交以及任何错误,以便用户可以更正表单并再次提交。
效果很好!
但是,在测试中我们现在遇到了一些问题。要测试 Controller ,您可以在测试中向它传递一个伪造的请求。可以通过将 nocheck header 添加到虚假请求来跳过 CSRF 检查本身,但是无法呈现 View ,因为没有可用于生成表单字段的 token 。测试失败,出现 RuntimeException,“缺少 CSRF token (csrf.scala:51)”。
鉴于它在实际运行时有效但在测试中无效,这似乎一定是 FakeRequests 在 Play 测试中运行的方式有问题,但我可能做错了什么。我已经按照 http://www.playframework.com/documentation/2.2.1/ScalaCsrf 中的说明实现了 CSRF 保护。和 http://www.playframework.com/documentation/2.2.1/ScalaFunctionalTest 中描述的测试.如果有人成功测试了受 CSRF 保护的表单,我将不胜感激。
最佳答案
一种解决方案是使用浏览器进行测试,例如 Fluentlenium,因为这将管理 cookie 等,因此 CSRF 保护应该都能正常工作。
另一种解决方案是向 FakeRequest 添加一个 session ,以便它包含一个 token ,例如:
FakeRequest().withSession("csrfToken" -> CSRF.SignedTokenProvider.generateToken)
显然,如果您经常这样做,您可以创建一个帮助方法来为您做这件事。
关于scala - 使用 CSRF 保护测试 scala Play (2.2.1) Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19838347/