Testing scala Play (2.2.1) controllers with CSRF protection

前端 未结 6 929
清歌不尽
清歌不尽 2021-01-13 17:21

I\'ve been having some problems testing controllers that use Play\'s CSRF protection. To demonstrate this, I\'ve created a very simple Play application that minimally exhibi

相关标签:
6条回答
  • 2021-01-13 17:35

    To those that are still interested: I managed to solve this problem globally by enabling CSRF protection in tests. The app will then create a token for every request that does not contain one. See my answer to this question

    0 讨论(0)
  • 2021-01-13 17:42

    Bonus answer for those interested in Java: I got this to work in the Java version of Play Framework 2.2 by adding

    .withSession(CSRF.TokenName(), CSRFFilter.apply$default$5().generateToken())
    

    to fakeRequest()

    0 讨论(0)
  • 2021-01-13 17:47

    Following on from @plade, I added a helper method to my base test class:

    protected static FakeRequest csrfRequest(String method, String url) {
        String token = CSRFFilter.apply$default$5().generateToken();
        return fakeRequest(method, url + "?csrfToken=" + token)
            .withSession(CSRF.TokenName(), token);
    }
    
    0 讨论(0)
  • 2021-01-13 17:48

    I use the following method in my base integration test class:

    def csrfRequest(method: String, uri: String)(implicit app: Application): FakeRequest[AnyContentAsEmpty.type] = {
      val tokenProvider: TokenProvider = app.injector.instanceOf[TokenProvider]
      val csrfTags = Map(Token.NameRequestTag -> "csrfToken", Token.RequestTag -> tokenProvider.generateToken)
      FakeRequest(method, uri, FakeHeaders(), AnyContentAsEmpty, tags = csrfTags)
    }
    

    Then you can use it in your tests where you would use FakeRequest.

    0 讨论(0)
  • 2021-01-13 17:50

    One solution is to test using a browser, eg Fluentlenium, as this will manage cookies etc, so the CSRF protection should all just work.

    The other solution is to add a session to the FakeRequest so that it contains a token, eg:

    FakeRequest().withSession("csrfToken" -> CSRF.SignedTokenProvider.generateToken)
    

    Obviously if you're doing that a lot, you can create a help method to do that for you.

    0 讨论(0)
  • 2021-01-13 17:55

    For those who might be interested, I created a trait for play 2.5.x : https://stackoverflow.com/a/40259536/3894835

    You can then use it in your tests requests like the addToken{} of the controller :

    val fakeRequest = addToken(FakeRequest(/* params */))
    
    0 讨论(0)
提交回复
热议问题