我是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");
}
}
我做错了什么?
答案 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)
}
然后您将摆脱此问题。