mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-07-12 21:33:30 +00:00
Merge branch '6.5.x'
This commit is contained in:
commit
ec16322000
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2025 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.security.config.http;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.messaging.simp.SimpMessageType;
|
||||||
|
import org.springframework.security.messaging.util.matcher.MessageMatcher;
|
||||||
|
import org.springframework.security.messaging.util.matcher.PathPatternMessageMatcher;
|
||||||
|
import org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher;
|
||||||
|
import org.springframework.util.AntPathMatcher;
|
||||||
|
import org.springframework.util.PathMatcher;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public final class MessageMatcherFactoryBean implements FactoryBean<MessageMatcher<?>>, ApplicationContextAware {
|
||||||
|
|
||||||
|
private PathPatternMessageMatcher.Builder builder;
|
||||||
|
|
||||||
|
private final SimpMessageType method;
|
||||||
|
|
||||||
|
private final String path;
|
||||||
|
|
||||||
|
private PathMatcher pathMatcher = new AntPathMatcher();
|
||||||
|
|
||||||
|
public MessageMatcherFactoryBean(String path) {
|
||||||
|
this(path, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageMatcherFactoryBean(String path, SimpMessageType method) {
|
||||||
|
this.method = method;
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageMatcher<?> getObject() throws Exception {
|
||||||
|
if (this.builder != null) {
|
||||||
|
return this.builder.matcher(this.method, this.path);
|
||||||
|
}
|
||||||
|
if (this.method == SimpMessageType.SUBSCRIBE) {
|
||||||
|
return SimpDestinationMessageMatcher.createSubscribeMatcher(this.path, this.pathMatcher);
|
||||||
|
}
|
||||||
|
if (this.method == SimpMessageType.MESSAGE) {
|
||||||
|
return SimpDestinationMessageMatcher.createMessageMatcher(this.path, this.pathMatcher);
|
||||||
|
}
|
||||||
|
return new SimpDestinationMessageMatcher(this.path, this.pathMatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getObjectType() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPathMatcher(PathMatcher pathMatcher) {
|
||||||
|
this.pathMatcher = pathMatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||||
|
this.builder = context.getBeanProvider(PathPatternMessageMatcher.Builder.class).getIfUnique();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,6 +19,7 @@ package org.springframework.security.config.web.messaging;
|
|||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.security.messaging.access.intercept.MessageMatcherDelegatingAuthorizationManager;
|
import org.springframework.security.messaging.access.intercept.MessageMatcherDelegatingAuthorizationManager;
|
||||||
import org.springframework.security.messaging.util.matcher.PathPatternMessageMatcher;
|
import org.springframework.security.messaging.util.matcher.PathPatternMessageMatcher;
|
||||||
|
import org.springframework.web.util.pattern.PathPatternParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this factory bean to configure the {@link PathPatternMessageMatcher.Builder} bean
|
* Use this factory bean to configure the {@link PathPatternMessageMatcher.Builder} bean
|
||||||
@ -31,9 +32,30 @@ import org.springframework.security.messaging.util.matcher.PathPatternMessageMat
|
|||||||
public final class PathPatternMessageMatcherBuilderFactoryBean
|
public final class PathPatternMessageMatcherBuilderFactoryBean
|
||||||
implements FactoryBean<PathPatternMessageMatcher.Builder> {
|
implements FactoryBean<PathPatternMessageMatcher.Builder> {
|
||||||
|
|
||||||
|
private PathPatternParser parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create {@link PathPatternMessageMatcher}s using
|
||||||
|
* {@link PathPatternParser#defaultInstance}
|
||||||
|
*/
|
||||||
|
public PathPatternMessageMatcherBuilderFactoryBean() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create {@link PathPatternMessageMatcher}s using the given {@link PathPatternParser}
|
||||||
|
* @param parser the {@link PathPatternParser} to use
|
||||||
|
*/
|
||||||
|
public PathPatternMessageMatcherBuilderFactoryBean(PathPatternParser parser) {
|
||||||
|
this.parser = parser;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PathPatternMessageMatcher.Builder getObject() throws Exception {
|
public PathPatternMessageMatcher.Builder getObject() throws Exception {
|
||||||
return PathPatternMessageMatcher.withDefaults();
|
if (this.parser == null) {
|
||||||
|
return PathPatternMessageMatcher.withDefaults();
|
||||||
|
}
|
||||||
|
return PathPatternMessageMatcher.withPathPatternParser(this.parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -55,6 +55,7 @@ import org.springframework.security.authorization.AuthorizationDecision;
|
|||||||
import org.springframework.security.authorization.AuthorizationManager;
|
import org.springframework.security.authorization.AuthorizationManager;
|
||||||
import org.springframework.security.authorization.AuthorizationResult;
|
import org.springframework.security.authorization.AuthorizationResult;
|
||||||
import org.springframework.security.config.Elements;
|
import org.springframework.security.config.Elements;
|
||||||
|
import org.springframework.security.config.http.MessageMatcherFactoryBean;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
@ -68,7 +69,6 @@ import org.springframework.security.messaging.access.intercept.MessageMatcherDel
|
|||||||
import org.springframework.security.messaging.context.AuthenticationPrincipalArgumentResolver;
|
import org.springframework.security.messaging.context.AuthenticationPrincipalArgumentResolver;
|
||||||
import org.springframework.security.messaging.context.SecurityContextChannelInterceptor;
|
import org.springframework.security.messaging.context.SecurityContextChannelInterceptor;
|
||||||
import org.springframework.security.messaging.util.matcher.MessageMatcher;
|
import org.springframework.security.messaging.util.matcher.MessageMatcher;
|
||||||
import org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher;
|
|
||||||
import org.springframework.security.messaging.util.matcher.SimpMessageTypeMatcher;
|
import org.springframework.security.messaging.util.matcher.SimpMessageTypeMatcher;
|
||||||
import org.springframework.security.messaging.web.csrf.XorCsrfChannelInterceptor;
|
import org.springframework.security.messaging.web.csrf.XorCsrfChannelInterceptor;
|
||||||
import org.springframework.security.messaging.web.socket.server.CsrfTokenHandshakeInterceptor;
|
import org.springframework.security.messaging.web.socket.server.CsrfTokenHandshakeInterceptor;
|
||||||
@ -275,25 +275,18 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements
|
|||||||
matcher.addConstructorArgValue(messageType);
|
matcher.addConstructorArgValue(messageType);
|
||||||
return matcher.getBeanDefinition();
|
return matcher.getBeanDefinition();
|
||||||
}
|
}
|
||||||
String factoryName = null;
|
BeanDefinitionBuilder matcher = BeanDefinitionBuilder.rootBeanDefinition(MessageMatcherFactoryBean.class);
|
||||||
if (hasPattern && hasMessageType) {
|
matcher.addConstructorArgValue(matcherPattern);
|
||||||
|
if (hasMessageType) {
|
||||||
SimpMessageType type = SimpMessageType.valueOf(messageType);
|
SimpMessageType type = SimpMessageType.valueOf(messageType);
|
||||||
if (SimpMessageType.MESSAGE == type) {
|
matcher.addConstructorArgValue(type);
|
||||||
factoryName = "createMessageMatcher";
|
if (SimpMessageType.SUBSCRIBE != type && SimpMessageType.MESSAGE != type) {
|
||||||
}
|
|
||||||
else if (SimpMessageType.SUBSCRIBE == type) {
|
|
||||||
factoryName = "createSubscribeMatcher";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
parserContext.getReaderContext()
|
parserContext.getReaderContext()
|
||||||
.error("Cannot use intercept-websocket@message-type=" + messageType
|
.error("Cannot use intercept-websocket@message-type=" + messageType
|
||||||
+ " with a pattern because the type does not have a destination.", interceptMessage);
|
+ " with a pattern because the type does not have a destination.", interceptMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BeanDefinitionBuilder matcher = BeanDefinitionBuilder.rootBeanDefinition(SimpDestinationMessageMatcher.class);
|
matcher.addPropertyValue("pathMatcher", new RuntimeBeanReference("springSecurityMessagePathMatcher"));
|
||||||
matcher.setFactoryMethod(factoryName);
|
|
||||||
matcher.addConstructorArgValue(matcherPattern);
|
|
||||||
matcher.addConstructorArgValue(new RuntimeBeanReference("springSecurityMessagePathMatcher"));
|
|
||||||
return matcher.getBeanDefinition();
|
return matcher.getBeanDefinition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,6 +342,32 @@ public class WebSocketMessageBrokerConfigTests {
|
|||||||
.withCauseInstanceOf(AccessDeniedException.class);
|
.withCauseInstanceOf(AccessDeniedException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenPathPatternFactoryBeanThenConstructsPatternsWithPathPattern() {
|
||||||
|
this.spring.configLocations(xml("SubscribeInterceptTypePathPattern")).autowire();
|
||||||
|
Message<?> message = message("/permitAll", SimpMessageType.SUBSCRIBE);
|
||||||
|
send(message);
|
||||||
|
message = message("/permitAll", SimpMessageType.UNSUBSCRIBE);
|
||||||
|
assertThatExceptionOfType(Exception.class).isThrownBy(send(message))
|
||||||
|
.withCauseInstanceOf(AccessDeniedException.class);
|
||||||
|
message = message("/anyOther", SimpMessageType.SUBSCRIBE);
|
||||||
|
assertThatExceptionOfType(Exception.class).isThrownBy(send(message))
|
||||||
|
.withCauseInstanceOf(AccessDeniedException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenCaseInsensitivePathPatternParserThenMatchesMixedCase() {
|
||||||
|
this.spring.configLocations(xml("SubscribeInterceptTypePathPatternParser")).autowire();
|
||||||
|
Message<?> message = message("/peRmItAll", SimpMessageType.SUBSCRIBE);
|
||||||
|
send(message);
|
||||||
|
message = message("/peRmKtAll", SimpMessageType.UNSUBSCRIBE);
|
||||||
|
assertThatExceptionOfType(Exception.class).isThrownBy(send(message))
|
||||||
|
.withCauseInstanceOf(AccessDeniedException.class);
|
||||||
|
message = message("/aNyOtHer", SimpMessageType.SUBSCRIBE);
|
||||||
|
assertThatExceptionOfType(Exception.class).isThrownBy(send(message))
|
||||||
|
.withCauseInstanceOf(AccessDeniedException.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void configureWhenUsingConnectMessageTypeThenAutowireFails() {
|
public void configureWhenUsingConnectMessageTypeThenAutowireFails() {
|
||||||
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright 2002-2018 the original author or authors.
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.springframework.org/schema/security"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<b:import resource="classpath:org/springframework/security/config/websocket/controllers.xml"/>
|
||||||
|
<b:import resource="classpath:org/springframework/security/config/websocket/websocket.xml"/>
|
||||||
|
|
||||||
|
<websocket-message-broker>
|
||||||
|
<intercept-message pattern="/permitAll" type="SUBSCRIBE" access="permitAll"/>
|
||||||
|
<intercept-message pattern="/**" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
<b:bean class="org.springframework.security.config.web.messaging.PathPatternMessageMatcherBuilderFactoryBean"/>
|
||||||
|
</b:beans>
|
@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright 2002-2018 the original author or authors.
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.springframework.org/schema/security"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<b:import resource="classpath:org/springframework/security/config/websocket/controllers.xml"/>
|
||||||
|
<b:import resource="classpath:org/springframework/security/config/websocket/websocket.xml"/>
|
||||||
|
|
||||||
|
<websocket-message-broker>
|
||||||
|
<intercept-message pattern="/permitAll" type="SUBSCRIBE" access="permitAll"/>
|
||||||
|
<intercept-message pattern="/**" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
<b:bean name="pathPatternParser" class="org.springframework.web.util.pattern.PathPatternParser">
|
||||||
|
<b:property name="caseSensitive" value="false"/>
|
||||||
|
</b:bean>
|
||||||
|
|
||||||
|
<b:bean class="org.springframework.security.config.web.messaging.PathPatternMessageMatcherBuilderFactoryBean">
|
||||||
|
<b:constructor-arg ref="pathPatternParser"/>
|
||||||
|
</b:bean>
|
||||||
|
</b:beans>
|
Loading…
x
Reference in New Issue
Block a user