Play框架上的Web服务不接受POST消息

时间:2018-02-21 11:39:26

标签: playframework-2.6

我将以下消息从Angular Service发送到播放应用程序

  public createUser(user:User):any{
    console.log('contacting server at '+this.API_URL +this.ADD_USER_URL +" with user data ",user);
    /*http.post returns an observable. The caller's code should subscribe to this observable */
    return this.http.post(this.API_URL +this.ADD_USER_URL,user)
      .map(response => { //handler if post's Observable is successful. map creates new User and returns Observable<User>.
        console.log('response from backend service',response);
        //return new User(response); //the constructor of User allows passing an object.
        /*when the observable of http.post returns (produces) data (the response), the map function prints a message and returns that response*/
        return response;
      })
      .catch(this.handleError); //error handler if Observable fails
  }

我在Play的控制台和禁止的响应中收到以下警告。 [warn] p.filters.CSRF - [CSRF] Check failed because application/json for request /ws/users/add

WebToBackendInterfaceService::handleError 
Object { headers: {…}, status: 403, statusText: "Forbidden", url: "http://localhost:9000/ws/users/add", ok: false, name: "HttpErrorResponse", message: "Http failure response for http://localhost:9000/ws/users/add: 403 Forbidden", error: "<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <title>Unauthorized</title>\n        <link rel=\"shortcut icon\" href=\"data:image/png;base64,...">\n        <style>\n            html, body, pre {\n                margin: 0;\n                padding: 0;\n                font-family: Monaco, 'Lucida Console', monospace;\n                background: #ECECEC;\n            }\n            h1 {\n                margin: 0;\n                background: #333;\n                padding: 20px 45px;\n                color: #fff;\n                text-shadow: 1px 1px 1px rgba(0,0,0,.3);\n                border-bottom: 1px solid #111;\n                font-size: 28px;\n            }\n            p#detail {\n                margin: 0;\n                padding: 15px 45px;\n                background: #888;\n                border-top: 4px solid #666;\n                color: #111;\n                text-shadow: 1px 1px 1px rgba(255,255,255,.3);\n                font-size: 14px;\n                border-bottom: 1px solid #333;\n            }\n        </style>\n    </head>\n    <body>\n        <h1>Unauthorized</h1>\n\n        <p id=\"detail\">\n            You must be authenticated to access this page.\n        </p>\n\n    </body>\n</html>\n" }

Play的CSRF似乎并不喜欢这条消息。我怎么能解决这个问题?我在Play中看到,错误发生在

  1. 请求不是GET,HEAD或Option - 在我的情况下是真的,我正在发送POST消息
  2. 请求包含cookie或授权标头。我没有明确发送它们。 Angular默认发送它吗?
  3. CORS过滤器未配置为信任请求的来源。 - 我正在向localhost发送请求:9000。不应该信任localhost吗?
  4. 我如何让Play接受我的信息?

2 个答案:

答案 0 :(得分:3)

这是一种解决方法。正确的解释在Angular not sending CSRF token in header。基本上,我的客户端应该发送一个带有最初由play框架创建的令牌的CSRF Header

我不知道这是否正确,但我必须在Play中禁用CSRF。它可以通过以下两种方式完成

routes文件中,在规则

上方添加nocsrf
+nocsrf
POST /ws/users/add                  controllers.UserController.addUser

或者在application.conf

中完全禁用csrf
play.filters {


  # Disabled filters remove elements from the enabled list.
  disabled += play.filters.csrf.CSRFFilter
}

我完全禁用了csrf

答案 1 :(得分:1)

确保您使用标题和cookie名称"Csrf-Token"设置了前端HTTP客户端。我的Angular + Play种子也遇到了同样的问题,事实证明,针对CSRF的Angular defaults cookie and header names是XSRF-TOKEN和X-XSRF-TOKEN。因此,在我的情况下,我必须导入另一个Angular模块以覆盖这些值:

  imports: [
    BrowserModule,
    ReactiveFormsModule,
    HttpClientModule,
    HttpClientXsrfModule.withOptions({
      cookieName: 'Csrf-Token',
      headerName: 'Csrf-Token',
    }),
    routing
  ]

尽管禁用Play的CSRF保护(基于Manu Chadha的回答)可能是一种解决方法,但强烈建议您这么做。