2014-09-24 100 views
4

我正在使用嵌入式Jetty的項目(不幸的是我只是「繼承」了項目的服務器端,並且不太熟悉Jetty及其配置的使用)。如何配置嵌入式Jetty來處理OPTIONS預檢請求?

一個奇怪的情況下,只需彈出 - 我會盡我所能來形容:

一個基於Web的用戶界面(使用AngularJS,從不同的域,因此使用CORS)發送POST請求改變服務器上的某種狀態。這在過去的某個時刻起作用(它可能在一個月左右之前被最後使用)。

昨天這停止工作。檢查REST調用,我看到OPTIONS請求首先被創建。 POST的內容類型是application/json,所以根據我讀過的內容,這是正確的。我不知道爲什麼以前沒有發送過 - 這家公司最近更新了Chrome版本,舊版本沒有發送預檢請求,但這只是猜測。在任何情況下,這裏就是我想在我的應用程序配置爲碼頭CORS相關代碼:

FilterHolder holder = new FilterHolder(new CrossOriginFilter()); 
holder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*"); 
holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true"); 
appHandler.addFilter(holder, "/*", EnumSet.of(DispatcherType.REQUEST)); 

一切正常POST請求。我可以通過使用--disable-web-security標誌啓動Chrome來驗證這一點。沒有發送OPTIONS請求,並且POST正常工作。

我的想法是,因爲它適用於POST,它不是授權或安全問題 - 只是Jetty沒有正確配置來處理預檢請求(它只返回401)。

我無法找到嵌入式Jetty的許多文檔,以及哪些CrossOriginFilter常量在調用setInitParameter時用作屬性鍵(此外,由於該方法調用的第二個參數是字符串,所以我確實有不知道如何格式化值)。

我應該在CrossOriginFilter上將哪些參數設置爲屬性句柄OPTIONS請求?如果我在上面說錯了或者做了任何錯誤的假設,請糾正我!這方面的經驗非常有限。

+1

你解決了這個問題嗎?如果是,請在此提供答案? – sag 2015-10-07 12:55:35

回答

1

的文檔CrossOriginFilter:

http://www.eclipse.org/jetty/documentation/current/cross-origin-filter.html

Javadoc文檔CrossOriginFilter:

http://download.eclipse.org/jetty/stable-9/apidocs/org/eclipse/jetty/servlets/CrossOriginFilter.html

實際的源代碼(有時這有助於人們瞭解得):

https://github.com/eclipse/jetty.project/blob/jetty-9.2.3.v20140905/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java

總之,您可能希望將OPTIONS添加到允許的方法中。

就像javadoc的說

FilterHolder holder = new FilterHolder(new CrossOriginFilter()); 
holder.setInitParameter("allowedMethods", "GET,POST,HEAD,OPTIONS"); 
appHandler.addFilter(holder, "/*", EnumSet.of(DispatcherType.REQUEST)); 

現在,以解決您有另一個錯誤......

這並沒有什麼...

holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, 
    "true"); 

也就是說不是初始參數鍵。(實際上,這是Access-Control-Allow-Credentials的標題名稱常量),如果您想允許憑據,請按照javadoc的說法操作。

holder.setInitParameter("allowCredentials", "true"); 
+0

謝謝 - 我已經發現,但我仍然無能爲力,爲什麼我得到一個401響應OPTIONS請求。 – Jer 2014-09-24 19:34:53

+0

我不確定技術上OPTIONS請求是否屬於CORS的「保護傘」,但OPTIONS請求仍然來自不同的域,當然(因爲POST嘗試來自不同的域)。我不確定代碼應該顯示什麼。它只是說爲了成爲預檢請求,方法*必須是* OPTIONS。我可能錯過了一些東西,但沒有任何東西被拒絕 - 如果有的話,一切*但*選項被拒絕。 – Jer 2014-09-24 21:14:37

-2

更新:我試了你的代碼,但我在上下文處理程序中添加了過濾器,而不是在應用程序上。它以這種方式工作。

 FilterHolder holder = new FilterHolder(new CrossOriginFilter()); 
    holder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "http://localhost:8100"); 
    holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true"); 

    contextHandler.addFilter(holder, "/*", EnumSet.of(DispatcherType.REQUEST)); 
+0

對不起,我沒有包含足夠的代碼。 'appHandler' *是* ServletContextHandler,它看起來像這樣:'ServletContextHandler appHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);' – Jer 2014-09-25 12:06:00

0

我用下面的配置爲FilterHolder解決了這個問題:

FilterHolder cors = new FilterHolder(CrossOriginFilter.class); 
cors.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*"); 
cors.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*"); 
cors.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "OPTIONS,GET,POST,HEAD"); 
cors.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Content-Type,Accept,Origin,Cache-Control"); 
cors.setInitParameter(CrossOriginFilter.CHAIN_PREFLIGHT_PARAM, "false"); 

Chrome瀏覽器發送一個「緩存控制」頭,如果你不允許你CORS過濾這個標題,然後OPTIONS請求將不會被正確的頭部響應。在線的CrossOriginFilter的大多數示例都不包含此標題。

您可以選擇將CHAIN_PREFLIGHT_PARAM設置爲false(默認爲true)。如果將其設置爲false,過濾器將響應請求而不將請求發送到Servlet。如果您想自己處理OPTIONS請求,則不需要設置此參數。

相關問題