gateway转发websocket显示403(Forbidden) 已解决
gateway结合websocket使用显示403(Forbidden)
因业务调整,需要在gateway中添加websocket的转发地址(PS:网上目前没有关于这个错误解决),原来的配置如下
代码可见,我在cors‐configurations配置了跨域信息,拦截所有请求,下面配置了websocket的路由规则。
代码如下
spring:
application:
name: api-gateway-server
cloud:
# 网关配置
gateway:
globalcors:
add-to-simple-url-handler-mapping: true
cors‐configurations:
'[/**]': # 匹配请求
# allowedOrigins: "*"
allowedOriginPatterns: '*' #跨域处理 允许所有的域
allowCredentials: true # 是否允许携带cookie
allowedMethods: # 支持的方法
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
# 路由配置
routes: # 集合
- id: websocket-reader-connect
uri: lb://library-system-reader
order: 2
predicates:
- Path=/librarySystemReader/websocket端点/info/**
filters:
- StripPrefix= 1
- id: websocket-reader
uri: lb:ws://library-system-reader
order: 3
predicates:
- Path=/librarySystemReader/websocket端点/**
filters:
- StripPrefix= 1
前端报跨域问题,检查发现我在gateway和项目websocket中都配置了AllowedOriginPattern,导致出现了两个Access-Control-Allow-Origin响应头。websocket原配置如下
代码贴上
//webSocket配置类
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
//注册端点
registry.addEndpoint("/librarySystemReader-websocket").setAllowedOriginPatterns("*").addInterceptors(new HttpHandShakeInterceptor()).withSockJS();
}
我将websocket配置中的setAllowedOriginPattern删除,本以为会连接成功,重启之后Stomp的get info显示403(Forbidden)。
不是最终解决办法
方法一:查问题最后发现如果想使用websocket,gateway不能配置跨域,原因不太清楚,第一种办法只能将gateway中的跨域注释掉,测试连接成功。
10月26日解决问题
方法二:和一些大佬交流之后,想到一个办法:
在gateway中设置过滤器检测websocket地址,删除gateway配置的跨域信息,使用websocket的跨域配置,在gateway中配置过滤器,设置此过滤器优先级最低。拦截websocket的请求将gateway配置的跨域头移除。
websocket、gateway采用之前的配置。
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class WebsocketFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getPath().pathWithinApplication().toString();
substring = path.substring(0, path.indexOf("/", path.indexOf("/", 2) + 1));
//检测websocket请求
if(substring.equals("/librarySystemReader/librarySystemReader-websocket")){
if(CorsUtils.isCorsRequest(request)){
//删除头信息
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().remove("Access-Control-Allow-Origin");
response.getHeaders().remove("Access-Control-Allow-Credentials");
}
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
//注意我将优先级设置最低
return 4;
}
}
测试结果连接成功!
下面是简单解释了一下websocket和http区别
1、WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。HTTP是单向的。
2、WebSocket是需要浏览器和服务器握手进行建立连接的。而http是浏览器发起向服务器的连接,服务器预先并不知道这个连接。
联系
3、WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。
更多推荐
所有评论(0)