spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
56.7k stars 38.14k forks source link

SockJS client does not use HttpHeaders passed by WebSocketConnectionManager for ServerInfo request [SPR-13254] #17845

Closed spring-projects-issues closed 9 years ago

spring-projects-issues commented 9 years ago

Holger Schott opened SPR-13254 and commented

SockJSClient does a ServerInfo request to obtain capabilities supported by SockJS server. The websocket endpoint is secured with BASIC AUTH, thus i need to pass in valid credentials by adding HttpHeaders to the WebSocketConnectionManager. When using raw rfc-6455 websockets the user gets authenticated and everything is fine. But when using SockJS with RestTemplateXhrTransport and WebSocketTransport the user will not be authenticated while the SockJSClient does the ServerInfo request. The HttpHeaders added to the WebSocketConnectionManager will not be used for the ServerInfo request. As a workaround i can configure a RestTemplateXhrTransport as InfoReceiver and pass in the HttpHeaders there, but then i have to configure the authentication credentials twice. And thats not what i want.


Affects: 4.1.6

Referenced from: commits https://github.com/spring-projects/spring-framework/commit/b7bdd724b2eab6959eade7868cfb1ecf21aa118b

spring-projects-issues commented 9 years ago

Rossen Stoyanchev commented

That's actually intended behavior. The headers on WebSocketConnectionManager are for the handshake request. When using SockJsClient with an XhrTransport you can set headers for all HTTP requests via on AbstractXhrTransport#setRequestHeaders (the two sets are not necessarily the same). Since XhrTransport implementations are also InfoReceiver implementations, that also includes the info request. By the way, you don't need to explicitly set an InfoReceiver on SockJsClient since the configured XhrTransport is automatically detected as InfoReceiver and used as such, see Javadoc on setInfoReceiver.

spring-projects-issues commented 9 years ago

Holger Schott commented

Hi Rossen, for me the ServerInfo request is a prequel part of the Websocket handshake for SockJs as implemented in SockJsClient.doHandshake(WebSocketHandler handler, WebSocketHttpHeaders headers, URI url). The given HttpHeader parameter should also be used to do the ServerInfo request. Regards, Holger

spring-projects-issues commented 9 years ago

Rossen Stoyanchev commented

That's a fair point. However it still doesn't take away the fact that all subsequent HTTP requests (long polling, streaming, HTTP POST to send messages) will need to pick up the auth headers as well. What we can do is to have an additional property on WebSocketConnectionManager that can be used to provide authorization headers separately. If the WebSocketClient is a SockJsClient, those headers would be used for all HTTP requests.

spring-projects-issues commented 9 years ago

Holger Schott commented

That is true. All subsequent requests should also be aware of an 'Authorization' header. A possible solution: Selected HttpHeaders given on SockJsClient.doHandshake() should be added to all transports, if not already present there.

spring-projects-issues commented 9 years ago

Rossen Stoyanchev commented

I've updated SockJsClient to apply handshake headers to other HTTP requests related to the same connection. There is also an additional property on SockJsClient to optionally restrict the handshake headers to use with other HTTP requests to a subset. By default all handshake headers are used. See commit b7bdd7.