簡體   English   中英

為什么Jetty JSR356在checkOrigin和ModifyHandshake方面表現不同

[英]Why does Jetty JSR356 behave differently with regards to checkOrigin and modifyHandshake

我通過連接一個Web套接字端點來玩弄Jetty( 9.2.3v20140905 ),當我遇到Jetty的代碼來查看如何使用它時,我嘗試使用自己的ServerEndpointConfig 我注意到在創建Web套接字對象時在JsrCreator使用了它:

Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp){
 ...
 // modify handshake
 configurator.modifyHandshake(config,hsreq,hsresp);
 ...
}

我閱讀了ServerEndpointConfigjavax.websocket-api 1.0 )的modifyHandshake的Javadoc,其中指出:

在容器制定了由格式正確的握手請求產生的握手響應之后,由容器調用。 容器已經檢查了此配置是否具有匹配的URI ,已使用checkOrigin方法確定了來源的有效性,並根據此配置填寫了協商的子協議和擴展名。 定制配置可能會覆蓋此方法,以便檢查請求參數並修改服務器已制定的握手響應。 以及URI檢查。 如果開發人員未重寫此方法,則實現將不對請求和響應進行進一步的修改。

這是Jetty的工作:

Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp){
 ...
 // modify handshake
 configurator.modifyHandshake(config,hsreq,hsresp);

 // check origin
 if (!configurator.checkOrigin(req.getOrigin())){...}
 ...
 resp.setAcceptedSubProtocol(subprotocol);
 ...
 resp.setExtensions(configs);
}

如您所見,在調用配置程序檢查了原點。 響應在配置器被調用后被修改。 WebSocketServerFactory acceptWebSocket方法調用WebSocketCreator:

Object websocketPojo = creator.createWebSocket(sockreq, sockresp);

然后調用:

private boolean upgrade(HttpConnection http, ServletUpgradeRequest request, ServletUpgradeResponse response, EventDriver driver)

它還通過HandshakeRFC6455修改響應:

 // build response
 response.setHeader("Upgrade","WebSocket");
 response.addHeader("Connection","Upgrade");
 response.addHeader("Sec-WebSocket-Accept",AcceptHash.hashKey(key));

因此,我無法僅使用我的配置器來修改響應,因為Jetty仍會更改它。

在我看來,Jetty不符合JSR 356(WebSocket的Java API),對嗎?

啊,JSR-356規范中許多含糊不清的部分之一。

您可能需要閱讀針對規范開放錯誤

如果嚴格遵循原始的1.x規范,則有很多真實的場景示例將無法實現。

現在,解決您的問題的具體細節:

為什么在Jetty實現中的ModifyHandshake之后調用checkOrigin?

這是因為存在有效的方案(尤其是CDI和Spring),在checkOrigin情況下,最終用戶的checkOrigin實現所需的信息無效或存在,直到調用modifyHandshake調用為止。

基本上,將創建端點Configurator ,並調用modifyHandshake ,然后,所有庫集成(CDI,Spring等)開始,此時端點進入WebSocket(RFC6455)CONNECTING狀態。 (一旦調用了端點的onOpen,則WebSocket RFC6455狀態將變為OPEN狀態)

您可能已經注意到,涉及CDI(或Spring)時,對象范圍和生存期的規范中沒有定義。

1.x JSR356規范實際上與servlet容器特定的行為保持距離,這樣做是為了使該規范盡可能通用,同時也具有非servlet websocket服務器容器的能力。 不幸的是,這還意味着servlet容器中有許多用例與1.x JSR356規范不兼容。

一旦更新了JSR356規范以在WebSocket上正確定義CDI范圍,那么即可解決checkOrigin之后的modifyHandshake怪癖。

為什么實現在ModifyHandshake之后修改響應?

實現必須修改響應,否則響應對於HTTP / 1.1升級是無效的,實現需要與終結點及其配置,子協議和擴展配合使用,這使這成為現實。 (注意,JSR356規范會擴展嗎?)

這也是一個有望在下一個JSR356修訂版中得到糾正的領域。

基於HTTP / 2規范的WebSocket的當前工作使這一點變得更加有趣,因為(當前)它不使用HTTP / 1.1升級語義。 它只是通過握手而存在(沒有升級,沒有起源等)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM