Java 播放框架CSRF错误“;[CSRF]检查失败,因为在标头中找不到令牌;

Java 播放框架CSRF错误“;[CSRF]检查失败,因为在标头中找不到令牌;,java,playframework,Java,Playframework,我是游戏框架中的新手,正在尝试提交表单,但是 获取此错误:“p.filters.CSRF-[CSRF]检查失败,因为在标头中找不到令牌”。我正在使用Play 2.6,以下是我的控制器代码: package controllers; import play.libs.Json; import play.mvc.*; import views.html.*; import java.util.ArrayList; import java.util.List; import java.u

我是游戏框架中的新手,正在尝试提交表单,但是 获取此错误:“p.filters.CSRF-[CSRF]检查失败,因为在标头中找不到令牌”。我正在使用Play 2.6,以下是我的控制器代码:

    package controllers;

import play.libs.Json;
import play.mvc.*;

import views.html.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HomeController extends Controller {

    public Result index() {
        return ok(index.render("Your new application is ready."));
    }

    public Result test() {
        List<String> list = new ArrayList<>();
        list.add("Jobs");
        list.add("Work");
        list.add("Say");
        list.add("Stop");
        return ok(test.render("test", list));
    }

    public Result testPost() {
       Map<String,String[]> form =  request().body().asFormUrlEncoded();
       return ok(Json.toJson(form)).as("application/json");
    }

}
包控制器;
导入play.libs.Json;
导入play.mvc.*;
导入视图;
导入java.util.ArrayList;
导入java.util.List;
导入java.util.Map;
公共类HomeController扩展控制器{
公开结果索引(){
返回ok(index.render(“新应用程序准备就绪”);
}
公开结果测试(){
列表=新的ArrayList();
列表。添加(“工作”);
列表。添加(“工作”);
列表。添加(“说”);
列表。添加(“停止”);
返回ok(test.render(“test”,list));
}
公共结果testPost(){
映射表单=请求().body().asFormUrlEncoded();
返回ok(Json.toJson(form)).as(“application/Json”);
}
}
模板:

@(title: String, list: List[String])

@import helper._

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>@title</title>
    </head>
    <body>
        <form action="/test" method="post">
            <textarea name="raw_text">

            </textarea>
            @CSRF.formField
            <input type="submit" value="Submit" />
        </form>
    </body>
</html>
@(标题:字符串,列表:列表[字符串])
@导入助手_
@头衔
@CSRF.formField

我做错了什么?

我找不到你的代码有任何错误,所以在本地设置一个相同的播放项目。 提交表单时,我没有碰到这个问题。 这是通过以下方式创建的基础项目:

sbt new playframework/play-java-seed.g8
将“Testing Testing”作为textArea的内容发布将返回以下Json(如浏览器所示):

我从自己的项目中得到的一个东西是修改后的Filters类,如下所示:

import play.mvc.EssentialFilter;
import play.filters.cors.CORSFilter;
import play.http.HttpFilters;
import play.filters.csrf.CSRFFilter;
import play.filters.headers.SecurityHeadersFilter;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.Arrays;
public class Filters implements HttpFilters {
    @Inject 
    CSRFFilter csrfFilter;
    @Inject
    CORSFilter corsFilter;
    @Inject 
    SecurityHeadersFilter secHeaders;

    @Override
    public List<EssentialFilter> getFilters() {

        return Arrays.<EssentialFilter>asList(new EssentialFilter[] { corsFilter.asJava(),secHeaders.asJava(), csrfFilter.asJava()});
                }
}
删除@CSRF.formField会导致与您一样的未经授权的CSRF


如果您的设置有任何明显的差异,我很乐意进一步挖掘,但这似乎不是您的代码的直接问题。

我已经遇到了它。我很简单地解决了这个问题。只需添加到application.conf:

在路由文件中,在路由之前添加nocsrf修改器标记:

+nocsrf
POST        /login                     controllers.AuthController.authorize()
就这样。。
我希望我的回答能帮助你。谢谢大家!

这可能不适用于所有情况,但在我的情况下,原因是我正在控制器中重置会话,因此CSRF令牌以某种方式变得无效


如果您在代码中调用“withNewSession”时出现此错误,请尝试将其删除,然后查看错误是否消失。

杜曼·詹博拉托夫的回答是错误的。是的,这样做可以避免错误,但这不是答案。它会将应用程序推向安全漏洞

应用程序面临问题的原因是表单页面请求播放会话(或您自定义的会话名称)cookie为空,其中csrfToken=value应该被加密。因为cookies中的csrfToken=value已被删除。如果发送带有新会话或丢弃cookie的响应,则可能会发生这种情况。 因此,如果您放弃cookie或使用新会话发送响应,请使用csrfToken=valuesession发送响应

def logout: Action[AnyContent] = Action {
    implicit request =>
      val csrfToken = CSRF.getToken.get.value

      Ok(logIn("Please log in")).withNewSession.withSession("csrfToken"->csrfToken)

  }  

那你就可以解决这个问题了

我用同样的方法创建了这个项目,现在一切都很好。但是,当我在这里使用play java starter示例时,仍然会出现此错误。那么,这可能是一个筛选器配置问题,请参阅下面的页面:“如果您已经了解Play并希望立即创建新项目,那么这是一个不错的选择。请注意,seed模板已经配置了CSRF和security headers过滤器,而其他项目并没有专门针对开箱即用的安全性进行设置。“明天我会看看基地的设置。应答中的Sbt命令使用种子模板。干杯。我对从play-scala-seed.g8模板创建的scala项目也有同样的问题。我按照文档中的规定传递了CSRF令牌,但未经授权,在控制台中我看到:p.a.m.DefaultJWTCookieDataCodec-decode:无法解码JWT:JWT签名与本地计算的签名不匹配。无法断言JWT有效性,不应信任JWT有效性。io.jsonwebtoken.SignatureException:JWT签名与本地计算的签名不匹配。无法断言JWT有效性,不应信任JWT有效性,[CSRF]检查失败,因为在标头中找不到令牌。我使用了@CSRF.formField东西。好的,它在我重新启动play-怪异后开始工作。
/login
听起来此控制器将从用户处接收表单。在该路线上禁用CSRF过滤器会破坏使用该过滤器的目的。但当这是一个受到其他保护的API端点时,它非常方便。如果其他人刚刚使用剪影框架遇到此问题,您至少可以使用此答案来确认是否可以绕过此问题。在我的情况下,
POST/signIn
call令人窒息。一旦发布了新的会话令牌,就不会再有问题了。
play.filters.enabled += "play.filters.csrf.CSRFFilter"
+nocsrf
POST        /login                     controllers.AuthController.authorize()
def logout: Action[AnyContent] = Action {
    implicit request =>
      val csrfToken = CSRF.getToken.get.value

      Ok(logIn("Please log in")).withNewSession.withSession("csrfToken"->csrfToken)

  }