spring的websocket访问时403
注:仅支持关闭sockjs的情况,如果需要开启sockjs,那么以下内容就不用看了
先说解决方案,在配置websocket的xml语句块中:
<websocket:handlers allowed-origins="*">
</websocket:handlers>
添加allowed-origins属性,具体值看自己的需要,如有多个用 “,”隔开。
原因:下面是spring在初始化websocket的相关代码
class HandlersBeanDefinitionParser implements BeanDefinitionParser {
private static final String SOCK_JS_SCHEDULER_NAME = "SockJsScheduler";
private static final int DEFAULT_MAPPING_ORDER = 1;
@Override
public BeanDefinition parse(Element element, ParserContext context) {
Object source = context.extractSource(element);
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
context.pushContainingComponent(compDefinition);
String orderAttribute = element.getAttribute("order");
int order = orderAttribute.isEmpty() ? DEFAULT_MAPPING_ORDER : Integer.valueOf(orderAttribute);
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(WebSocketHandlerMapping.class);
handlerMappingDef.setSource(source);
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
handlerMappingDef.getPropertyValues().add("order", order);
String handlerMappingName = context.getReaderContext().registerWithGeneratedName(handlerMappingDef);
RuntimeBeanReference sockJsService = WebSocketNamespaceUtils.registerSockJsService(
element, SOCK_JS_SCHEDULER_NAME, context, source);
HandlerMappingStrategy strategy;
// 以下为主要代码
if (sockJsService != null) {
strategy = new SockJsHandlerMappingStrategy(sockJsService);
}
else {
RuntimeBeanReference handshakeHandler = WebSocketNamespaceUtils.registerHandshakeHandler(element, context, source);
Element interceptorsElement = DomUtils.getChildElementByTagName(element, "handshake-interceptors");
ManagedList<? super Object> interceptors = WebSocketNamespaceUtils.parseBeanSubElements(interceptorsElement, context);
String allowedOriginsAttribute = element.getAttribute("allowed-origins");
List<String> allowedOrigins = Arrays.asList(StringUtils.tokenizeToStringArray(allowedOriginsAttribute, ","));
interceptors.add(new OriginHandshakeInterceptor(allowedOrigins));
strategy = new WebSocketHandlerMappingStrategy(handshakeHandler, interceptors);
}
ManagedMap<String, Object> urlMap = new ManagedMap<String, Object>();
urlMap.setSource(source);
for (Element mappingElement : DomUtils.getChildElementsByTagName(element, "mapping")) {
strategy.addMapping(mappingElement, urlMap, context);
}
handlerMappingDef.getPropertyValues().add("urlMap", urlMap);
context.registerComponent(new BeanComponentDefinition(handlerMappingDef, handlerMappingName));
context.popAndRegisterContainingComponent();
return null;
}
// 其他代码已省略
}
应该可以看到,如果开启sockjs则不会执行else代码块中代码,那么为了执行else代码块就必须关闭sockjs。所以该方式仅支持关闭sockjs。
在 websocket:handlers 标签添加 allowed-origins属性以后,会在生成默认拦截器时,将allowed-origins的值注入,这样就可以解决访问时出现403的错误。
注:也可以通过写配置类的方式,不过其他人都写得很详细了,在这里就不在多说。更加详细的说明请见springmvc官方文档,上面写得很清楚,这里贴出来仅仅是因为自己还不是很熟悉,官方文档写道很清楚的。