如何在 Spring 5.3 及更高版本中使用 Stomp 和 SockJS 处理 CORS 起源?
Posted
技术标签:
【中文标题】如何在 Spring 5.3 及更高版本中使用 Stomp 和 SockJS 处理 CORS 起源?【英文标题】:How to handle CORS origins with Stomp and SockJS in Spring 5.3 and newer? 【发布时间】:2021-03-15 16:02:14 【问题描述】:我正在开发一个同时使用 REST 端点和 SockJS websocket 的服务器应用程序。这曾经在 Spring 5.2 及更低版本下运行良好。
但是,从 5.3 版本开始,org.springframework.web.cors.CorsConfiguration
中存在以下方法:
public void validateAllowCredentials()
if (this.allowCredentials == Boolean.TRUE &&
this.allowedOrigins != null && this.allowedOrigins.contains(ALL))
throw new IllegalArgumentException(
"When allowCredentials is true, allowedOrigins cannot contain the special value \"*\"" +
"since that cannot be set on the \"Access-Control-Allow-Origin\" response header. " +
"To allow credentials to a set of origins, list them explicitly " +
"or consider using \"allowedOriginPatterns\" instead.");
到目前为止,我的套接字是这样配置的:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer
@Override
public void configureMessageBroker(MessageBrokerRegistry config)
// prefix for the client to send messages to the server
config.setApplicationDestinationPrefixes("/app");
// prefix for the client to receive broadcasted messages from the server
config.enableSimpleBroker("/topic");
@Override
public void registerStompEndpoints(StompEndpointRegistry registry)
// defines the url of the socket so the client can connect to it
registry.addEndpoint("/socketendpoint").setAllowedOrigins("*").withSockJS();
现在我面临一个真正的问题:
如果我将setAllowedOrigins("*")
保留在WebSocketConfiguration
中,那么我将面临validateAllowCredentials
中抛出的错误。
如果我删除 setAllowedOrigins("*")
,那么 SockJS 客户端将收到 Error during WebSocket handshake: Unexpected response code: 403
。
我在编译时不知道源域。
我已经尝试了一个 Cors 过滤器和一个 Cors 配置,它们使用典型的“将您在请求中找到的 origin
标头返回为 allow-origin
”模式,该模式通常用于规避 allow-origin: "*"
,但一些 SockJS 请求没有分配origin
标头...
我该如何解决这个问题?
【问题讨论】:
对于没有 Origin 请求标头的请求,不要在响应中发送 Access-Control-Allow-Origin 标头,因为无论这些请求来自哪里,它们re 不是来自将在响应中查找 Access-Control-Allow-Origin 标头的浏览器。唯一对 Access-Control-Allow-Origin 标头有任何用途的用户代理,甚至浏览器也只关心它只对浏览器本身添加了 Origin 标头的请求的响应。因此,任何缺少 Origin 标头的请求都不需要响应中的 Access-Control-Allow-Origin。 你能找到解决办法吗? 我们选择延迟依赖升级。 Spring 存储库最近已经提交了关于此问题的提交,它应该包含在即将发布的版本之一中;不知道它是否已经出来了。 【参考方案1】:为了将来参考,随着最新的春季更新,现在有一个方法setAllowedOriginPatterns
可以解决这个问题:
registry.addEndpoint("/socketendpoint").setAllowedOriginPatterns("*").withSockJS();
【讨论】:
对我来说,它修复了错误,但我不再收到其他 Spring 应用程序的任何消息。它发送一条消息,但没有收到任何消息。它适用于早期的 Spring Boot 版本(2.2 及更早版本) 嗨,我正在尝试使用 corsfilter(在 spring security 中)和“setAllowedOriginPatterns("*")”(在 websocketconfig 中)访问“/websocket”端点。但是,通过同时保留它会给出“'Access-Control-Allow-Origin' 中的多个值”并从其中一个中删除,它会显示“没有 Access-Control-Allow-Origin 标头”或 403 错误。如何访问 websocket 端点?【参考方案2】:来自文档
配置允许的 Origin 标头值。这个检查主要是设计的 对于浏览器客户端。没有什么可以阻止其他类型的客户 修改 Origin 标头值。当启用 SockJS 和起源时 受到限制,不允许检查请求的传输类型 origin(基于 iframe 的传输)被禁用。因此,IE 6 当来源受到限制时,不支持到 9。 每个提供 允许的来源必须以“http://”、“https://”或“*”开头(表示 允许所有来源)。 默认情况下,只有相同来源的请求 被允许(空列表)。自从: 4.1.2 另见:RFC 6454: The Web Origin Concept , SockJS support transports by browser
你的代码
registry.addEndpoint("/socketendpoint").setAllowedOrigins("*").setAllowedOrigins().withSockJS();
应该是
registry.addEndpoint("/socketendpoint").setAllowedOrigins("*").withSockJS();
【讨论】:
对不起,原来的问题有错误;必须沿着复制粘贴的路线潜入代码 sn-p 并将其修剪回相关部分。现在已经修好了。以上是关于如何在 Spring 5.3 及更高版本中使用 Stomp 和 SockJS 处理 CORS 起源?的主要内容,如果未能解决你的问题,请参考以下文章
在 Java 11 及更高版本中使用 HttpClient 时如何跟踪 HTTP 303 状态代码?
registerForRemoteNotificationTypes:iOS 8.0及更高版本不支持
如何使用 RxAlamofire 或 Alamofire 5 及更高版本检查相同的 DataRequest 是不是已经在进行中? [关闭]