Play Framework 2.4.x 中的 CORS 疑难解答

Posted

技术标签:

【中文标题】Play Framework 2.4.x 中的 CORS 疑难解答【英文标题】:Trouble-shooting CORS in Play Framework 2.4.x 【发布时间】:2015-11-05 15:59:07 【问题描述】:

我有一个提供 JSON/HTTP API 的 java play framework 2.4.x Web 应用程序。当我运行我的前端 html/JS file:///Users/nize/tmp/index.htmlhttp://localhost:9000 上调用 API 时,chrome 显示

XMLHttpRequest cannot load http://localhost:9000. 
No 'Access-Control-Allow-Origin' header is present 
on the requested resource. Origin 'null' is therefore 
not allowed access. The response had HTTP status code 403.

我已按照Play Framework 2.4.x CORS Documentation 中的说明配置了网络应用程序:

更新为build.sbt 将类Filters.java添加到项目的根目录(也尝试过/app) 在application.conf 中添加了以下节:
play.filters.cors 
  allowedOrigins = ["*","http://localhost"]
  #allowedHttpMethods = ["GET", "POST"]
  #allowedHttpHeaders = ["Accept"]
  #preflightMaxAge = 3 days

我错过了什么?

编辑: 症状看起来与Other very similar *** post 相同或相似。该问题通过重新配置安装在计算机上的 Cisco AnyConnect *** 得到解决。但是,我没有安装该软件。

【问题讨论】:

在我查看下面的答案之前,您的问题已经帮助了我。我只实现了文档中说明的最后一部分(在 application.conf 中配置 CORS 过滤器),缺少前两个(更新 build.sbt 并添加 Filters.java)。所以我一直在玩游戏,直到我偶然发现你的问题总结了我从官方文档中遗漏的步骤,以及下面的 Radium 答案,链接到reference.conf。顺便说一句,我使用的是 Firefox,并且在 Chrome 上也成功测试过,所以这对我来说不是 Chrome 特有的问题,甚至不应该是。 @nize 你能解决这个问题吗?我有完全相同的问题。我还定义了一个控制器方法来处理 OPTIONS 请求,但无济于事。我总是使用 Ajax 和 Postman 得到 403 【参考方案1】:

首先将这些行(配置)添加/编辑到您的 conf/application.conf 中

 play.filters.cors 
  # allow all paths
  pathPrefixes = ["/"]
  # allow all origins (You can specify if you want)
  allowedOrigins = null
  allowedHttpMethods = ["GET", "POST", "PUT", "DELETE"]
  # allow all headers
  allowedHttpHeaders = null
    

(请注意,以“#”开头的行是注释行。)

然后去 build.sbt 并添加这一行。

libraryDependencies += filters

最后创建一个名为“Filters.java”的 Java 类并将其包含到根目录 (/app)。

import play.api.mvc.EssentialFilter;
import play.filters.cors.CORSFilter;
import play.http.HttpFilters;

import javax.inject.Inject;

public class Filters implements HttpFilters 

    @Inject
    CORSFilter corsFilter;

    public EssentialFilter[] filters() 
        return new EssentialFilter[]  corsFilter ;
    

您可以参考official documentation了解更多信息。

【讨论】:

非常适合我,谢谢。请注意,默认 app.conf 文件已经有 cors 配置 - 这只是取消注释/编辑相关设置的情况。 类型不匹配:无法从 CORSFilter 转换为 EssentialFilter @cyril 你用的是什么播放版本? corsFilter.asJava() 2.5 版没问题,谢谢【参考方案2】:
filters = "filters.Filters"


play.filters 

  cors 

    # The allowed origins. If null, all origins are allowed.
    allowedOrigins = null

    # The allowed HTTP methods. If null, all methods are allowed
    allowedHttpMethods = null

    # The allowed HTTP headers. If null, all  headers are allowed.
    allowedHttpHeaders = null
  





public class Filters implements HttpFilters 

    @Inject
    private CORSFilter corsFilter;

    public EssentialFilter[] filters() 
        return new EssentialFilter[] 
            corsFilter.asJava()
        ;
    


【讨论】:

【参考方案3】:

我认为CORS filter in Play 不起作用!我一步一步地跟着,但不知何故,我总是在 Ajax 调用中的浏览器(Chrome 和 Firefox)中得到 HTTP-403。问题是我什至没有在服务器端获得堆栈跟踪。我认为 CORS 过滤器中的 DefaultHttpErrorHandler 以某种方式吞下它。在响应中缺少“Access-Control-Allow-Origin”标头,所以我只是手动添加。

class Filters @Inject() (corsFilter: CORSFilter, log: LoggingFilter) extends HttpFilters 
  def filters = 
    // CORS filter does not work
    //Seq(corsFilter, log)
    Seq(log)
  

这是日志过滤器(来源:Play!框架)

class LoggingFilter extends Filter 

  def apply(nextFilter: RequestHeader => Future[Result])(requestHeader: RequestHeader): Future[Result] = 

    val startTime = System.currentTimeMillis

    nextFilter(requestHeader).map  result =>

      val endTime = System.currentTimeMillis
      val requestTime = endTime - startTime

      Logger.info(s"$requestHeader.method $requestHeader.uri " +
        s"took $requestTimems and returned $result.header.status")

      result.withHeaders(
        "Request-Time" -> requestTime.toString,
        "Access-Control-Allow-Origin" -> "*"   // Added this header
      )
    
  

【讨论】:

【参考方案4】:

我遇到了类似的问题,我收到了 403 的请求。我通过删除:

allowedHttpHeaders=["Accept"] 

他们在示例配置中使用。但是,我仍然不清楚这对安全的影响是什么,所以 YMMV。

【讨论】:

这对我也有用。我也不确定这会带来什么安全隐患。【参考方案5】:

这可能无法解决发帖者的问题,但是当我有相同的症状时,它为我解决了问题,我发布它以防它可以帮助处于相同情况的其他人。

我实际上误解了 CORS 的工作原理。我有两个独立的 Play 应用程序,一个带有 REST API,另一个带有使用 REST API 的 Web 界面。我按照问题中提到的文档页面中的说明进行操作,但我的错误是我在 Web 界面应用程序上进行了操作。当我改为在 REST API 应用程序上执行此操作时,它立即生效。

【讨论】:

【参考方案6】:

我在遵循相同的文档时遇到了同样的问题。

问题在于您使用的这个 CORS 过滤器:

allowedOrigins = ["*","http://localhost"]

如果您想允许所有来源使用:

allowedOrigins = null

allowedHttpMethods 也一样

这是根据documentation

引用:

允许的来源。如果为 null,则允许所有来源。

allowedOrigins = null

希望这会有所帮助!

【讨论】:

【参考方案7】:

它在 Firefox 中有效吗? Chrome 对从本地文件运行 Ajax 有一些限制,例如,请参阅 this link。如果是 Chrome 特定的,您可以使用命令行开关启动 Chrome 以消除限制。

【讨论】:

好点。我也尝试使用 firefox (MacOS),但我得到了 403(禁止)。 对于我在 chrome、firefox 和 explorer 中工作的配置:***.com/questions/38315501/…

以上是关于Play Framework 2.4.x 中的 CORS 疑难解答的主要内容,如果未能解决你的问题,请参考以下文章

Play Framework [2.4.x] 如何在子模块的路由文件中处理公共资产

Play Framework 2.4.x - 覆盖默认的 Actor 系统创建

Play Framework 2.4.x 自定义部署脚本

迁移到 2.4.x (Java) 后在 Play Framework 中运行测试时出错

Play Framework 2.5.x 中的 HikariCP 警告消息

Play Framework:如何不查看文件夹以了解 Play Framework 中的更改