Spring Cloud Gateway集成Spring Security时无法建立WebSocket连接
无法通过Spring Cloud Gateway建立WebSocket连接
我正在开发一个依赖WebSocket连接的应用,已完成包含WebSocket配置的Spring Boot微服务notification-service,并通过集成了Spring Security的gateway-service(端口8747)暴露该微服务的所有API。
前端测试代码
用于测试WebSocket连接的前端代码如下:
<html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.js"></script> <script type="text/javascript"> var stompClient = null; const LOCAL_URL = 'http://localhost:8747/websocket/notification-service/ws'; var socket = new SockJS(LOCAL_URL); stompClient = Stomp.over(socket); stompClient.connect({}, function(frame) { console.log(frame); stompClient.subscribe('/topic/notification', function(result) { show(JSON.parse(result.body)); }); }); function sendMessage() { var text = document.getElementById('text').value; stompClient.send("/app/application", {}, JSON.stringify({'text':text})); } function show(message) { var response = document.getElementById('messages'); var p = document.createElement('p'); p.innerHTML= "message: " + message.message; response.appendChild(p); } </script> </head> <body> <div> <div> <button id="sendMessage" onclick="sendMessage();">Send</button> <input type="text" id="text" placeholder="Text"/> </div> <br /> <div> <button id="sendPrivateMessage" onclick="sendPrivateMessage();">Send Private</button> <input type="text" id="privateText" placeholder="Private Message"/> <input type="text" id="to" placeholder="To"/> </div> <br /> <br /> <br /> <div id="messages"></div> </div> </body> </html>
Gateway服务配置
Spring Security配置
已将WebSocket相关端点加入白名单:
@Configuration @EnableWebFluxSecurity public class SecurityConfig { private static final String[] AUTH_WHITE_LIST = { "/websocket/sds-notification-service/**" }; @Bean public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { return http .csrf(ServerHttpSecurity.CsrfSpec::disable) .authorizeExchange(exchanges -> exchanges.pathMatchers(AUTH_WHITE_LIST) .permitAll() .anyExchange().authenticated()) .build(); } }
全局响应过滤器
@Configuration public class GlobalResponseFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return chain.filter(exchange).then(Mono.fromRunnable(() -> { var response = exchange.getResponse(); var request = exchange.getRequest(); response.getHeaders().set("Access-Control-Allow-Credentials", "true"); response.getHeaders().set("Access-Control-Allow-Origin", request.getHeaders().getOrigin()); exchange.mutate().response(response).build(); })); } @Override public int getOrder() { return 0; } }
自定义权限验证过滤器
我还实现了一个用于权限验证的AuthorizationFilter,代码如下:
@Component public class AuthorizationFilter extends AbstractGatewayFilterFactory<AuthorizationFilter.Config> { public AuthorizationFilter() { super(Config.class); } @Override public GatewayFilter apply(Config config) { return ((exchange, chain) -> ReactiveSecurityContextHolder.getContext() .map(securityContext -> { if (someValidateLogic()) { return chain.filter(exchange); } else { return Mono.error(new AuthorizationServiceException(HttpStatus.FORBIDDEN.toString())); } }) .flatMap(classMono -> classMono) .then()); } }
问题描述
当前无法建立WebSocket连接,控制台报错。但移除上述自定义AuthorizationFilter后,WebSocket连接可正常建立,推测是过滤器顺序配置有误导致的问题。
内容的提问来源于stack exchange,提问作者iuhettiarachchi
相关产品推荐
相关产品推荐

