Play Framework CSRF错误" [CSRF]检查失败,因为在标题中找不到令牌"

时间:2017-07-02 15:49:23

标签: java playframework

我是Play Framework的新手,并尝试提交表单,但是 得到此错误:" p.filters.CSRF - [CSRF]检查失败,因为在标题中找不到令牌" 。我使用Play 2.6,这是我的控制器代码:

public static void main(String[] args) {
    repeated((byte) 1);       // casting int 1 to byte, so repeated(byte) is invoked
    repeated(1);              // 1 is int, so repeated(int) is invoked
    repeated((int) 1.0);      // casting double 1.0 to int, so repeated(int) is invoked
    repeated((int) 1L);       // casting long 1 to int, so repeated(int) is invoked 
    repeated(1L);             // 1L is long number, so repeated(long) is invoked
    repeated((long) 1);       // casting int 1 to long, so repeated(long) is invoked
    repeated((long) 1.0);     // casting double 1.0 to long, so repeated(long) is invoked
    repeated(1.0);            // 1.0 is double so repeated(double) is invoked
    repeated((double) 1);     // casting int 1 to double, so repeated(double) is invoked
    repeated((double) 1L);    // casting long 1 to double, so repeated(double) is invoked
    repeated(new Integer(1)); // new Integer(1) is Integer so repeated(Integer) is invoked
    repeated((Integer) 1);    // casting int 1 to Integer, so repeated(Integer) is invoked
                              // conversion from int to Integer and vice-versa are natively supported
    repeated(new Object());   // new Object() is Object, so repeated(Object) is invoked
    repeated((Object) new Integer(1)); // casting Integer to Object, so repeated(Object) is invoked
                                       // upcasting to supertype (Integer extends Object)
}

public static void repeated(byte a) {System.out.println("repeated(byte)");}
public static void repeated(int a) {System.out.println("repeated(int)");}
public static void repeated(long a) {System.out.println("repeated(long)");}
public static void repeated(double a) {System.out.println("repeated(double)");}
public static void repeated(Integer a) {System.out.println("repeated(Integer)");}
public static void repeated(Object a) {System.out.println("repeated(Object)");}

模板:

    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");
    }

}

我做错了什么?

4 个答案:

答案 0 :(得分:4)

我已经面对了。我非常简单地解决了它。只需添加到您的 application.conf

play.filters.enabled += "play.filters.csrf.CSRFFilter"

,并在 routes 文件中,在路由之前添加nocsrf修饰符标记:

+nocsrf
POST        /login                     controllers.AuthController.authorize()

就是这样。 希望我的回答对您有所帮助。谢谢!

答案 1 :(得分:1)

我无法找到您的代码有任何问题,因此请在本地设置一个相同的Play项目。 提交表单时,我没有遇到这个问题。 这是通过以下方式创建的基础项目:

sbt new playframework/play-java-seed.g8

发布&#34;测试测试&#34;因为textArea的内容返回以下Json(由浏览器显示):

raw_text    
0   "            Testing testing"
csrfToken   
0   "8fdc72b2d628e4fc0d8f6359f2ea247cc0f22e5c-1499016237415-3c043ab2a02c18020df21a1f"

我从自己的项目中得到的一件事是修改后的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()});
                }
}

我的路线在conf / routes中如下:

# Map static resources from the /public folder to the /assets URL path
GET     /assets/*file               controllers.Assets.versioned(path="/public", file: Asset)
GET / controllers.HomeController.test()
POST /test controllers.HomeController.testPost()

删除@ CSRF.formField会导致CSRF被授权,就像您一样。

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

Duman Zhanbolatov的答案是错误的。是的,这样做可以避免错误,但这不是答案。它将把应用程序推向安全漏洞。

应用程序面临问题的原因是表单页面请求 PLAY_SESSION (或您的自定义会话名称)Cookie为空,其中csrfToken = value应该具有被刻印了。因为不知何故Cookie中的 csrfToken = value 已被删除。如果您发送带有新会话的响应或丢弃cookie,则可能会发生这种情况。 因此,如果您丢弃cookie或使用新会话发送响应,请通过 csrfToken = value 会话发送它。

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

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

  }  

然后您将摆脱此问题。