网站首页 > 文章精选 正文
将springboot升级到2.4.0后websocket报跨域问题,报错如下:
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.
经过跟代码发现是spring5.3以上的一个函数:
Bash
/**
* Validate that when {@link #setAllowCredentials allowCredentials} is true,
* {@link #setAllowedOrigins allowedOrigins} does not contain the special
* value {@code "*"} since in that case the "Access-Control-Allow-Origin"
* cannot be set to {@code "*"}.
* @throws IllegalArgumentException if the validation fails
* @since 5.3
*/
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.");
}
}
解决办法:
1 继承SimpleUrlHandlerMapping重写getConfiguration函数
Bash
package com.iscas.base.biz.config.stomp;
import org.springframework.context.Lifecycle;
import org.springframework.context.SmartLifecycle;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
/**
* 升级springboot到2.4.0后websocket出现跨域问题处理,重写MyWebSocketHandlerMapping
*
* @author zhuquanwen
* @vesion 1.0
* @date 2020/11/25 13:59
* @since jdk1.8
*/
public class MyWebSocketHandlerMapping extends SimpleUrlHandlerMapping implements SmartLifecycle {
private volatile boolean running;
@Override
protected void initServletContext(ServletContext servletContext) {
for (Object handler : getUrlMap().values()) {
if (handler instanceof ServletContextAware) {
((ServletContextAware) handler).setServletContext(servletContext);
}
}
}
@Override
public void start() {
if (!isRunning()) {
this.running = true;
for (Object handler : getUrlMap().values()) {
if (handler instanceof Lifecycle) {
((Lifecycle) handler).start();
}
}
}
}
@Override
public void stop() {
if (isRunning()) {
this.running = false;
for (Object handler : getUrlMap().values()) {
if (handler instanceof Lifecycle) {
((Lifecycle) handler).stop();
}
}
}
}
@Override
public boolean isRunning() {
return this.running;
}
@Override
public CorsConfiguration getCorsConfiguration(Object handler, HttpServletRequest request) {
Object resolvedHandler = handler;
if (handler instanceof HandlerExecutionChain) {
resolvedHandler = ((HandlerExecutionChain) handler).getHandler();
}
if (resolvedHandler instanceof CorsConfigurationSource) {
// if (!this.suppressCors && (request.getHeader(HttpHeaders.ORIGIN) != null)) {
// }
// return null;
if (resolvedHandler instanceof SockJsHttpRequestHandler) {
String origin = request.getHeader("Origin");
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(new ArrayList<>(Arrays.asList(origin)));
config.addAllowedMethod("*");
config.setAllowCredentials(true);
config.setMaxAge(365 * 24 * 3600L);
config.addAllowedHeader("*");
return config;
} else {
return ((CorsConfigurationSource) resolvedHandler).getCorsConfiguration(request);
}
}
return null;
}
}
2 继承MyWebMvcStompEndpointRegistry重写getHandlerMapping函数
package com.iscas.base.biz.config.stomp;
import cn.hutool.core.util.ReflectUtil;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.util.MultiValueMap;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.WebMvcStompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebMvcStompWebSocketEndpointRegistration;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
import org.springframework.web.util.UrlPathHelper;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* 升级springboot到2.4.0后websocket出现跨域问题处理,重写WebMvcStompEndpointRegistry
*
* @author zhuquanwen
* @vesion 1.0
* @date 2020/11/25 13:44
* @since jdk1.8
*/
public class MyWebMvcStompEndpointRegistry extends WebMvcStompEndpointRegistry {
public MyWebMvcStompEndpointRegistry(WebSocketHandler webSocketHandler, WebSocketTransportRegistration transportRegistration, TaskScheduler defaultSockJsTaskScheduler) {
super(webSocketHandler, transportRegistration, defaultSockJsTaskScheduler);
}
public AbstractHandlerMapping getHandlerMapping() {
Map<String, Object> urlMap = new LinkedHashMap<>();
List<WebMvcStompWebSocketEndpointRegistration> registrations = null;
try {
registrations = (List<WebMvcStompWebSocketEndpointRegistration>) ReflectUtil.getFieldValue(this, "registrations");
} catch (Exception e) {
e.printStackTrace();
}
for (WebMvcStompWebSocketEndpointRegistration registration : registrations) {
MultiValueMap<HttpRequestHandler, String> mappings = registration.getMappings();
mappings.forEach((httpHandler, patterns) -> {
for (String pattern : patterns) {
urlMap.put(pattern, httpHandler);
}
});
}
MyWebSocketHandlerMapping hm = new MyWebSocketHandlerMapping();
hm.setUrlMap(urlMap);
int order = 1;
try {
order = (int) ReflectUtil.getFieldValue(this, "order");
} catch (Exception e) {
e.printStackTrace();
}
hm.setOrder(order);
UrlPathHelper urlPathHelper = null;
try {
urlPathHelper = (UrlPathHelper) ReflectUtil.getFieldValue(this, "urlPathHelper");
} catch (Exception e) {
e.printStackTrace();
}
if (urlPathHelper != null) {
hm.setUrlPathHelper(urlPathHelper);
}
return hm;
}
}
3 继承DelegatingWebSocketMessageBrokerConfiguration重写stompWebSocketHandlerMapping函数
package com.iscas.base.biz.config.stomp;
import cn.hutool.core.util.ReflectUtil;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.DelegatingWebSocketMessageBrokerConfiguration;
/**
* 升级springboot到2.4.0后websocket出现跨域问题处理,重写DelegatingWebSocketMessageBrokerConfiguration
*
* @author zhuquanwen
* @vesion 1.0
* @date 2020/11/25 13:12
* @since jdk1.8
*/
@Configuration
//@Primary
//@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyDelegatingWebSocketMessageBrokerConfiguration extends DelegatingWebSocketMessageBrokerConfiguration {
// @Bean
// @Primary
public HandlerMapping stompWebSocketHandlerMapping() {
WebSocketHandler handler = decorateWebSocketHandler(subProtocolWebSocketHandler());
MyWebMvcStompEndpointRegistry registry = new MyWebMvcStompEndpointRegistry(
handler, getTransportRegistration(), messageBrokerTaskScheduler());
ApplicationContext applicationContext = getApplicationContext();
if (applicationContext != null) {
try {
ReflectUtil.setFieldValue(this, "applicationContext", applicationContext);
} catch (Exception e) {
e.printStackTrace();
}
// registry.setApplicationContext(applicationContext);
}
registerStompEndpoints(registry);
return registry.getHandlerMapping();
}
}
猜你喜欢
- 2025-06-13 SpringBoot权限炸场!动态鉴权提速10倍吊打RBAC(附工具源码)
- 2025-06-13 Spring Boot 3.4 新特性实战解析(springboot最新)
- 2025-06-13 SpringBoot 2.7.10、3.0.5 发布,修复 DoS漏洞
- 2025-06-13 还在为 Spring Boot3 动态配置发愁?一文教你轻松搞定!
- 2025-06-13 SpringBoot几种动态修改配置的方法
- 2025-06-13 快来看看SpringBoot2.2发行版,你能用到哪些新特性?
- 2025-06-13 Spring Boot3 应用打包成 Docker 镜像全攻略
- 2025-06-13 Spring Boot3 动态配置实现方案全解析,你掌握了吗?
- 2025-06-13 Spring Framework 6.2 和 Spring Boot 3.4 为 2025 年新一代做好准备
- 2025-06-13 我找到了一个快速定位SpringBoot接口超时问题的神器
- 06-24PLC常用进制数及转换方法(plc中进制符号)
- 06-24PLC常用数制及转换方法,让你轻松掌握PLC编程
- 06-24PLC编程必看!5种常见进制数解析,搞懂才能玩转PLC!
- 06-24C数据类型——常量(c的数据类型及其定义方法)
- 06-24什么是二进制、八进制、十进制、十六进制?
- 06-24理论基础——十进制、二进制、十六进制、八进制
- 06-24搞不懂PLC中的高字节、低字位是啥?看完这篇文章就懂了!
- 06-242、进位制之间的转换(含有小数位)
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)