2016-08-16 200 views
9

我正在開發一個基於Play Framework 2.5(Java)後端的Angular 2應用程序。如果我通過瀏覽器URL訪問我的端點,它們工作正常。然而,從角2應用程序中調用它顯示的錯誤:CORS Play框架

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

我已經tryed跟隨documentation和創建過濾器:

在application.conf:

play.filters { 
    cors { 
    pathPrefixes = ["/app"] 
    allowedOrigins = null 
    allowedHttpMethods = null 
    } 

篩選:

import play.mvc.*; 
import play.api.http.DefaultHttpFilters; <- error with this import 
import play.filters.cors.CORSFilter; 

public class Filters extends DefaultHttpFilters { 
    @Inject public Filters(CORSFilter corsFilter) { 
     super(corsFilter); 
    } 
} 

In build.sbt:

libraryDependencies ++= Seq(
    ..., 
    filters 
) 

有沒有人知道真正的解決方案?謝謝:)

工作代碼:

Filters.java(在項目的根)

import com.google.inject.Inject; 
import com.google.inject.Singleton;  
import play.http.HttpFilters; 
import play.mvc.EssentialAction; 
import play.mvc.EssentialFilter; 
import play.filters.cors.CORSFilter; 

@Singleton 
public class Filters extends EssentialFilter implements HttpFilters { 

    @Inject 
    private CORSFilter corsFilter; 

    @Override 
    public EssentialAction apply(EssentialAction next) { 
     return corsFilter.asJava().apply(next); 
    } 

    @Override 
    public EssentialFilter[] filters() { 
     EssentialFilter[] result = new EssentialFilter[1]; 
     result[0] = this;  
     return result; 
    } 
} 

在application.conf:

#filters += Filters <- yes, it is commented since my Filters is in project's root 
libraryDependencies += filters 

play.filters { 
cors{ 
    # allow all paths 
    pathPrefixes = ["/"] 
    # allow all origins 
    allowedOrigins = null 
    allowedHttpMethods = ["GET", "POST", "PUT", "DELETE"] 
    # allow all headers 
    allowedHttpHeaders = null 
} ... 

在build.sbt:

libraryDependencies ++= Seq(
    ..., 
    filters 
) 

謝謝大家! :)

+0

需要在服務器上進行配置,並且與Angular無關。如果你使用'withCredentials',必須提供確切的原點而不是'*'。 CORS只適用於HTTP請求被設置爲不同的URL,然後index.html最初被加載的地方,這就是爲什麼它在你直接在瀏覽器中輸入URL的原因。 –

+0

我同意,這是服務器端。我不知道該怎麼做,或者找你的答案,對不起。 – Patriicya

+0

你在使用iFrames嗎? – amitmah

回答

1

我記得有相同的導入問題,因爲我認爲有一些重新打包過濾器在播放2.5.0左右的變化。 DefaultHttpFilters在重構期間被替換爲HttpFilters

檢查源代碼爲HttpFilters的正確路徑。選擇正在使用的Play版本的正確標籤,然後搜索源樹,直到找到HttpFilters並檢查包。 This is the path for the Java API for v 2.5.0

從你的文章看來你使用的是Java API,但是使用Scala版本的導入。

用於播放2.5.0的進口: -

斯卡拉 - import play.api.http.HttpFilters
爪哇 - import play.http.HttpFilters

我使用播放2.5.0(斯卡拉雖然 - 不是Java),這是進口爲我工作的罰款: -

import play.api.http.HttpFilters 

從你發佈的內容我認爲你應該嘗試改變你有問題的導入爲: -

import play.http.HttpFilters 

另外,(如其他人說)我假設你已經配置了包爲您Filters.java文件,如果你還沒有把它放在根包。

這是我application.conf項,因爲我使用package filters而不是默認的package.:-

play.http.filters = "filters.Filters" 
+0

這讓我非常接近解決方案,請檢查工作代碼。 – Patriicya

+0

for 2.6只需在配置中添加'play.filters.hosts allowed = [「localhost:9000」,「localhost:4200」] }'' – cutoffurmind

3

最佳做法是同時提供來自單一來源的靜態上下文和Web服務。例如,對於單個域,除/ api/*之外的每個URI都用於提供靜態內容,而/ api/*則是Java應用程序的反向代理。您可能對Grunt特別感興趣。 nginx和Apache也可以工作。

例如,在nginx的指定配置如下:

location /api { 
    rewrite /api/(.*) /$1 break; 
    proxy_pass http://127.0.0.1:9000; 
    proxy_redirect off; 
    proxy_set_header Host $host; 
    proxy_set_header X-Forwarded-For $remote_addr; 
} 

location/{ 
    root /var/www/location; 
    index index.html index.htm; 
} 

然後運行您的Java應用程序監聽本地主機,端口9000,您可以到所有的靜態內容複製到後指定位置「根「並通過nginx獲取它。您將所有REST請求發送到/ api/method/name

此解決方案的優點是穩固的安全性和輕鬆配置SSL的能力。

+0

你能解釋更多關於它或給我一些參考?謝謝。 – Patriicya

+0

當然。現在編輯答案。 – mkorman

+0

謝謝你的回答,但我真的需要知道如何在Play中做... – Patriicya

0

如果開發目的你可以用瀏覽器插件試圖阻止CORS檢查:

例如,cors everywhere在Firefox或Allow-Control-Allow-Origin在Chrome中。

無論如何,在生產環境中,您將不得不從同一個主機提供JS資產和服務,或者將Acces-Control-Allow-Origin標頭設置爲您服務的具體值。

+0

謝謝你的回答,它是針對生產環境的。 – Patriicya

0

我認爲自定義過濾器解決您的問題:

import javax.inject.Inject 

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

class Filters @Inject() (corsFilter: CORSFilter) 
    extends DefaultHttpFilters(corsFilter) 

application.conf

play.http.filters = "filters.MyFilters" 

配置是這樣的:

play.filters.cors { 
    pathPrefixes = ["/some/path", ...] 
    allowedOrigins = ["http://www.example.com", ...] 
    allowedHttpMethods = ["GET", "POST"] 
    allowedHttpHeaders = ["Accept"] 
    preflightMaxAge = 3 days 
} 
+0

根據規範我無法導入'play.api.http.DefaultHttpFilters'(找不到符號) – Patriicya

+0

,您必須追加'libraryDependencies + = filters'來查看:https://www.playframework.com/documentation /2.3.x/ScalaCsrf#applying-a-global-csrf-filter – pacman

+0

請檢查帖子(已更新)。 – Patriicya

0

你不顯示在你的項目很多,所以很難理解,這可能是一個什麼樣的問題。我認爲這裏沒有任何CORS問題,因爲默認情況下沒有任何安全過濾器處於活動狀態。您可以找到here,如何整合角度和播放。

+0

我已添加一些代碼的問題 – Patriicya

0

對於其他人用角4前端和後端lagom項目工作的緣故。我已經設法解決這個問題。

*我在下面在我的版本中添加了這一行。SBT在兩個API和實現*

libraryDependencies + =濾波器

以我IMPL目錄,我創建的文件夾的過濾器和加入下面

import play.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.asJava()}; 
    } 
} 

代碼以我application.conf我添加代碼如下

play.filters.hosts { 
    # Allow requests to example.com, its subdomains, and localhost:9000. 
    allowed = ["localhost:5000", "localhost:9000"] 
} 

play.http.filters = "....filters.Filters" 

play.filters.cors { 
    # Filter paths by a whitelist of path prefixes 
    pathPrefixes = ["/"] 

    # The allowed origins. If null, all origins are allowed. 
    allowedOrigins = null 
    allowedHttpMethods = ["GET", "POST"] 
    allowedHttpHeaders = ["Accept"] 
    preflightMaxAge = 3 days 
} 

之後,我重新啓動m y lagom微服務,它像一個魅力。