簡體   English   中英

向現有的Spring應用程序添加Web套接字支持

[英]Adding web socket support to an existing Spring application

我正在使用Spring 4應用程序(不幸的是,不是Spring Boot ),但是我無法使Web套接字正常工作。 有一個簡單的TextWebSocketHandler ,我在執行注冊/ws路徑, 得到一個確認日志:

將URL路徑[/ ws]映射到[class org.springframework.web.socket.server.support.WebSocketHttpRequestHandler]類型的處理程序上

...但是我無法使用網絡瀏覽器中的地址進行連接。 我已經嘗試過這種基於注釋的配置:

@Slf4j
@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer {
    public static final String WEB_SOCKET_PATH = "/ws";
    @Autowired
    private WebSocketService handler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        log.info("Registering web socket handler {} at '{}'.", handler, WEB_SOCKET_PATH);
        registry.addHandler(handler, WEB_SOCKET_PATH);
    }
}

我可以確認WebSocketService handler不為null,並且實際上實現了WebSocketHandler接口。 當配置程序明顯被觸發時,使用"ws://localhost:8081/ws"導致錯誤:

WebSocket與“ ws:// localhost:8081 / ws”的連接失敗:WebSocket握手期間出錯:意外的響應代碼:404

錯誤{目標:WebSocket,isTrusted:true,currentTarget:WebSocket,eventPhase:2,氣泡:false,可取消:false,defaultPrevented:false,時間戳:1469616712980247,originalTarget:WebSocket,explicitOriginalTarget:WebSocket,NONE:0}

我用來測試Web套接字機制的客戶端代碼非常簡單:

var ws = new WebSocket("ws://localhost:8081/ws");
ws.onerror = function(e) { console.log(e); }
ws.onopen = function() { console.log("Opened"); }

我什至嘗試通過XML配置注冊處理程序,但是雖然獲得的日志幾乎相同,但仍然無法正常工作。 請注意,我正在使用Jetty 9的許多默認配置(通過Gretty Gradle插件)運行該應用程序。

通過Spring調試日志時,我只能猜測Spring無法將HTTP請求提升為Web套接字連接:

13:14:02.322 [qtp1305935114-14] DEBUG - /ws at position 1 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
13:14:02.322 [qtp1305935114-14] DEBUG - Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@4190548c: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@4190548c: Principal: org.springframework.security.core.userdetails.User@58c7c40: Username: [removed]; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@12afc: RemoteIpAddress: 127.0.0.1; SessionId: 1om9yxo93cwce1qb1tu0rcs15n; Granted Authorities: ROLE_USER'
13:14:02.322 [qtp1305935114-14] DEBUG - /ws at position 2 of 13 in additional filter chain; firing Filter: 'ConcurrentSessionFilter'
13:14:02.322 [qtp1305935114-14] DEBUG - /ws at position 3 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
13:14:02.322 [qtp1305935114-14] DEBUG - /ws at position 4 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter'
13:14:02.322 [qtp1305935114-14] DEBUG - /ws at position 5 of 13 in additional filter chain; firing Filter: 'LogoutFilter'
13:14:02.322 [qtp1305935114-14] DEBUG - Checking match of request : '/ws'; against '/logout'
13:14:02.322 [qtp1305935114-14] DEBUG - /ws at position 6 of 13 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
13:14:02.322 [qtp1305935114-14] DEBUG - Request 'GET /ws' doesn't match 'POST /securityCheck
13:14:02.322 [qtp1305935114-14] DEBUG - /ws at position 7 of 13 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
13:14:02.322 [qtp1305935114-14] DEBUG - /ws at position 8 of 13 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
13:14:02.322 [qtp1305935114-14] DEBUG - /ws at position 9 of 13 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
13:14:02.322 [qtp1305935114-14] DEBUG - /ws at position 10 of 13 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
13:14:02.322 [qtp1305935114-14] DEBUG - SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@4190548c: Principal: org.springframework.security.core.userdetails.User@58c7c40: Username: [removed]; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@12afc: RemoteIpAddress: 127.0.0.1; SessionId: 1om9yxo93cwce1qb1tu0rcs15n; Granted Authorities: ROLE_USER'
13:14:02.322 [qtp1305935114-14] DEBUG - /ws at position 11 of 13 in additional filter chain; firing Filter: 'SessionManagementFilter'
13:14:02.322 [qtp1305935114-14] DEBUG - /ws at position 12 of 13 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
13:14:02.322 [qtp1305935114-14] DEBUG - /ws at position 13 of 13 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
13:14:02.322 [qtp1305935114-14] DEBUG - Checking match of request : '/ws'; against '/login*'
13:14:02.322 [qtp1305935114-14] DEBUG - Secure object: FilterInvocation: URL: /ws; Attributes: [ROLE_USER]
13:14:02.322 [qtp1305935114-14] DEBUG - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@4190548c: Principal: org.springframework.security.core.userdetails.User@58c7c40: Username: [removed]; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@12afc: RemoteIpAddress: 127.0.0.1; SessionId: 1om9yxo93cwce1qb1tu0rcs15n; Granted Authorities: ROLE_USER
13:14:02.322 [qtp1305935114-14] DEBUG - Voter: org.springframework.security.access.vote.RoleVoter@b5de58f, returned: 1
13:14:02.322 [qtp1305935114-14] DEBUG - Authorization successful
13:14:02.322 [qtp1305935114-14] DEBUG - RunAsManager did not change Authentication object
13:14:02.322 [qtp1305935114-14] DEBUG - /ws reached end of additional filter chain; proceeding with original chain
13:14:02.323 [qtp1305935114-14] DEBUG - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@425f619f
13:14:02.324 [qtp1305935114-14] DEBUG - Chain processed normally
13:14:02.324 [qtp1305935114-14] DEBUG - SecurityContextHolder now cleared, as request processing completed

瀏覽了官方文檔和示例后,似乎Web套接字配置是非常標准的。 為了在Spring中啟用Web套接字,我可能錯過了什么,或者可能需要更改任何配置嗎?

事實證明,Web套接字可以按預期工作,但未在web.xml中將Spring servlet映射設置為/*

<servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/spring/*</url-pattern>
</servlet-mapping>

這真是愚蠢的-我要做的就是將地址更改為ws://localhost:8081/spring/ws 讓我措手不及的是,一些Spring過濾器已映射到/*並且給人以Spring servlet共享此映射的印象-畢竟,對ws://localhost:8081/ws調用觸發了一些Spring東西(如在日志中看到)。

我認為您應該在WebSocketConfigurer類中添加@Controller批注,如果不是所有的http請求都將由Spring的DispatcherServlet處理。 相關: 找不到404的Spring Websocket

暫無
暫無

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

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