springboot2.4.x websocket跨域问题

1,springboot升级版本以后websocket连接出现以下错误

java.lang.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.

2,SpringBoot 2.4.0版本后解决跨域问题(较之前的版本有些变化)

请注意注释代码的替换:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings( CorsRegistry registry) {
        registry.addMapping("/**")//允许请求路径
                //.allowedOrigins("*")//表示允许所有网址发起跨域请求
                .allowedOriginPatterns("*")//表示允许所有网址发起跨域请求
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")//表示允许跨域请求的方法
                .allowedMethods("*")
                .maxAge(3600)//表示在3600秒内不需要再发送预校验请求
                .allowCredentials(true);//允许客户端携带验证信息,即允许携带cookie
    }
  
}

3,SpringBoot 2.4.0对应的websocket配置

请注意,2.4.X的SpringBoot对应的websocket跨域配置并没有setAllowedOriginPatterns这个方法,建议升级更高版本springboot,笔者亲测springboot2.5.6版本可以用

猜测:可能是SpringBoot2.4.X对springweb跨域底层做了修改,但是这个版本对应的websocket(5.3.1~5.3.9)并没有对此做出适配,建议使用SpringBoot更高版或降低版本。

package com.zl.config;


import com.zl.websocket.Operation;
import com.zl.websocket.message.MessageProcessor;
import com.zl.websocket.message.StompMessageConsumer;
import com.zl.websocket.message.StompMessagePusher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

/**
 * @Author zl
 * @Description
 * @Date 2022/8/22 21:40
 */
@Configuration
@EnableWebSocketMessageBroker
public class StompMessageConfig implements WebSocketMessageBrokerConfigurer {

    //protected static Logger LOGGER = LoggerFactory.getLogger(com.zn.stomp.configuration.StompMessageConfig.class);

    @Autowired(required = false)
    private Operation operation;

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        String endpointName = "endpoint";
        registry.addEndpoint(endpointName)

               
                //.setAllowedOrigins("*")
                .setAllowedOriginPatterns("*")

                .withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        String topicFixed = "/topic";
        String appFixed = "/app";
        String userFixed = "/user";
        registry.enableSimpleBroker(topicFixed, userFixed);
        registry.setApplicationDestinationPrefixes(appFixed);
        registry.setUserDestinationPrefix(userFixed);
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new ChannelInterceptor() {
            @Override
            public Message<?> preSend(Message<?> message, MessageChannel channel) {
                StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
                assert accessor != null;
                Object simpSessionId = message.getHeaders().get(SimpMessageHeaderAccessor.SESSION_ID_HEADER);
                if (simpSessionId instanceof String) {
                    if (operation == null) {
                       // LOGGER.error("Operation not found instance!!!");
                        return message;
                    }
                    operation.operation(accessor.getCommand(), (String) simpSessionId, message.getHeaders());
                }
                return message;
            }
        });
    }

    @Override
    public void configureClientOutboundChannel(ChannelRegistration registration) {
        if (operation == null) {
            return;
        }
        operation.clientOutboundChannel(registration);
    }

    @Bean
    public StompMessagePusher stompMessagePusher(SimpMessagingTemplate messagingTemplate){
        //LOGGER.info("spring auto create StompMessagePusher component.");
        return new StompMessagePusher(messagingTemplate);
    }

    @Bean
    @ConditionalOnBean(MessageProcessor.class)
    public StompMessageConsumer stompMessageConsumer(MessageProcessor messageProcessor){
        //LOGGER.info("spring auto create StompMessageConsumer component.");
        return new StompMessageConsumer(messageProcessor);
    }
}

 

posted @ 2022-08-23 19:02  风子磊  阅读(2099)  评论(0编辑  收藏  举报