在 Scala Play Framework v2.6.x 中出现 cors 错误

Posted

技术标签:

【中文标题】在 Scala Play Framework v2.6.x 中出现 cors 错误【英文标题】:Getting cors errors in Scala Play Framework v2.6.x 【发布时间】:2018-01-15 10:16:36 【问题描述】:

我正在尝试解决 Scala/Play 2.6.x 中简单的“hello world”样式 REST API 的 CORS 错误,并且我已经尝试了目前我能想到的所有方法。据我所知,在互联网上找不到一个好的解决方案或示例,所以即使这应该是一个简单的解决方案,那么任何有一个好的解决方案的人都会通过完整发布它来真正帮助我。我只是想从localhost:3000(使用 axios 的反应应用程序)向我的 Scala/Play 框架所在的localhost:9000 发送一个发布请求。

错误

我在客户端遇到的错误如下:

XMLHttpRequest cannot load http://localhost:9000/saveTest.
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:3000' is therefore not allowed
access. The response had HTTP status code 403.

我在服务器端遇到的错误是

success] Compiled in 1s

--- (RELOAD) ---

[info] p.a.h.EnabledFilters - Enabled Filters
(see <https://www.playframework.com/documentation/latest/Filters>):

    play.filters.csrf.CSRFFilter
    play.filters.headers.SecurityHeadersFilter
    play.filters.hosts.AllowedHostsFilter
    play.filters.cors.CORSFilter

[info] play.api.Play - Application started (Dev)
[warn] p.f.c.CORSFilter - Invalid CORS
request;Origin=Some(http://localhost:3000);
Method=OPTIONS;Access-Control-Request-Headers=Some(content-type)

我的代码

我的application.conf 文件中有以下内容

# https://www.playframework.com/documentation/latest/Configuration

play.filters.enabled += "play.filters.cors.CORSFilter"

play.filters.cors 
  pathPrefixes = ["/"]
  allowedOrigins = ["http://localhost:3000", ...]
  allowedHttpMethods = ["GET", "POST", "PUT", "DELETE"]
  allowedHttpHeaders = ["Accept"]
  preflightMaxAge = 3 days

我尝试将pathPrefixes 更改为/saveTest(我的端点),并尝试将allowedOrigins 更改为简单的'https://localhost'。我试过改变allowedHttpHeaders="Allow-access-control-allow-origin"。我尝试将 allowedOriginsallowedHttpMethodsallowedHttpHeaders 全部设置为 null,根据文档 (https://www.playframework.com/documentation/2.6.x/resources/confs/filters-helpers/reference.conf) 应该允许所有内容(pathPrefixes=["/"] 也应该允许)

我的 build.sbt 如下,所以应该是在 libraryDependencies 中添加过滤器:

name := """scalaREST"""
organization := "com.example"

version := "1.0-SNAPSHOT"

lazy val root = (project in file(".")).enablePlugins(PlayScala)

scalaVersion := "2.12.2"

libraryDependencies += guice
libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "3.1.0" % Test
libraryDependencies += filters

根据此处提供的文档:https://www.playframework.com/documentation/2.6.x/Filters#default-filters,您可以像这样设置默认过滤器:

import javax.inject.Inject

import play.filters.cors.CORSFilter
import play.api.http. DefaultHttpFilters, EnabledFilters 

class Filters @Inject()(enabledFilters: EnabledFilters, corsFilter: CORSFilter)
  extends DefaultHttpFilters(enabledFilters.filters :+ corsFilter: _*)

我不确定它应该在我的项目中的确切位置 - 它没有说,但从其他 *** 答案我有点假设它应该放在我的目录的根目录中(即/app)。所以这就是我放的地方。

最后,有一个奇异的 *** 响应说将这个类放在我的控制器中,并将它作为一个函数添加到我的 OK 响应中

  implicit class RichResult (result: Result) 
    def enableCors =  result.withHeaders(
      "Access-Control-Allow-Origin" -> "*"
      , "Access-Control-Allow-Methods" -> 
        "OPTIONS, GET, POST, PUT, DELETE, HEAD"
        // OPTIONS for pre-flight
      , "Access-Control-Allow-Headers" -> 
        "Accept, Content-Type, Origin, X-Json, 
        X-Prototype-Version, X-Requested-With"
        //, "X-My-NonStd-Option"
      , "Access-Control-Allow-Credentials" -> "true"
    )
  

不用说,这不起作用。

整理

这是我当前的 scala 项目的后端。

https://github.com/patientplatypus/scalaproject1/tree/master/scalarest

如果可以,请展示 CORS 实现的完整工作示例 - 我无法在网上找到任何可以工作的东西。我可能会将其作为文档请求提交给 Play Framework 组织——这应该不是那么困难。谢谢。

【问题讨论】:

好的....我知道它必须是 200,但它不是。这只是对问题的简单重述。考虑到我在前端收到错误消息,说明这是一个 CORS 问题,我很确定这是一个 CORS 问题。我绝不是不屑一顾,但我不确定这如何让我更接近解决方案。 ***.com/questions/31975439/… 可能是相关的 我已经尝试过该解决方案,但它不起作用。 你调试过 CORSFilter 并根据它所说的“无效来源”弄清楚了吗? 当然,我可以告诉你的是,我可以使用 play 2.6 来完成所有工作,我通过调试过滤器来做到这一点,这有助于我了解发生了什么以及我需要调整哪些设置.我不是说你会在那里找到一个错误,但你可能会看到有什么东西往南走。 【参考方案1】:

我也遇到了这个问题,我在 application.conf 中添加了这些代码

play.filters.enabled += "play.filters.cors.CORSFilter"
play.filters.cors 
  allowedHttpMethods = ["GET", "HEAD", "POST"]
  allowedHttpHeaders = ["Accept", "Content-Type"]"

现在一切正常!

for more info

【讨论】:

【参考方案2】:

您的预检请求失败,因为您设置了 Content-Type 标头

在您的application.conf 中添加content-typeallowedHttpHeaders,就像这样

#application.conf

play.filters.cors 
  #other cors configuration
  allowedHttpHeaders = ["Accept", "Content-Type"]
 

【讨论】:

以上是关于在 Scala Play Framework v2.6.x 中出现 cors 错误的主要内容,如果未能解决你的问题,请参考以下文章

在 Play Framework 2.4 中为 Scala 实现 Akka

在 Play Framework 2.4 中为 Scala 实现 CORS

Scala Play Framework,在哪里创建演员?

Play Framework Routes 中的 Scala 反引号

如何将 IntelliJ 与 Play Framework 和 Scala 一起使用

如何在 Play Framework 2.0 (Scala) 中插入测试数据?