Message SecurityExpressionHandler is post processed (#3820)

Previously the SecurityExpressionHandler for message based configuration
did not have a beanResolver set.

This commit post processes the default message SecurityExpressionHandler
to ensure the beanResolver is set.

Fixes gh-3797
This commit is contained in:
Rob Winch 2016-04-19 12:21:58 -05:00 committed by Joe Grandja
parent c872a77ad1
commit a5a8aeb550
2 changed files with 45 additions and 6 deletions

View File

@ -24,6 +24,7 @@ import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.messaging.Message;
@ -33,7 +34,10 @@ import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.expression.SecurityExpressionHandler;
import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
import org.springframework.security.config.annotation.web.messaging.MessageSecurityMetadataSourceRegistry;
import org.springframework.security.messaging.access.expression.DefaultMessageSecurityExpressionHandler;
import org.springframework.security.messaging.access.expression.MessageExpressionVoter;
import org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor;
import org.springframework.security.messaging.access.intercept.MessageSecurityMetadataSource;
@ -78,10 +82,13 @@ import org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsSe
* @author Rob Winch
*/
@Order(Ordered.HIGHEST_PRECEDENCE + 100)
@Import(ObjectPostProcessorConfiguration.class)
public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends
AbstractWebSocketMessageBrokerConfigurer implements SmartInitializingSingleton {
private final WebSocketMessageSecurityMetadataSourceRegistry inboundRegistry = new WebSocketMessageSecurityMetadataSourceRegistry();
private SecurityExpressionHandler<Message<Object>> defaultExpressionHandler = new DefaultMessageSecurityExpressionHandler<Object>();
private SecurityExpressionHandler<Message<Object>> expressionHandler;
private ApplicationContext context;
@ -150,9 +157,7 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends
ChannelSecurityInterceptor channelSecurityInterceptor = new ChannelSecurityInterceptor(
inboundMessageSecurityMetadataSource());
MessageExpressionVoter<Object> voter = new MessageExpressionVoter<Object>();
if(expressionHandler != null) {
voter.setExpressionHandler(expressionHandler);
}
voter.setExpressionHandler(getMessageExpressionHandler());
List<AccessDecisionVoter<? extends Object>> voters = new ArrayList<AccessDecisionVoter<? extends Object>>();
voters.add(voter);
@ -169,9 +174,7 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends
@Bean
public MessageSecurityMetadataSource inboundMessageSecurityMetadataSource() {
if(expressionHandler != null) {
inboundRegistry.expressionHandler(expressionHandler);
}
inboundRegistry.expressionHandler(getMessageExpressionHandler());
configureInbound(inboundRegistry);
return inboundRegistry.createMetadataSource();
}
@ -218,6 +221,18 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends
}
}
@Autowired(required = false)
public void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
defaultExpressionHandler = objectPostProcessor.postProcess(defaultExpressionHandler);
}
private SecurityExpressionHandler<Message<Object>> getMessageExpressionHandler() {
if(expressionHandler == null) {
return defaultExpressionHandler;
}
return expressionHandler;
}
public void afterSingletonsInstantiated() {
if (sameOriginDisabled()) {
return;

View File

@ -117,6 +117,15 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
clientInboundChannel().send(message("/permitAll"));
}
// gh-3797
@Test
public void beanResolver() {
loadConfig(SockJsSecurityConfig.class);
messageUser = null;
clientInboundChannel().send(message("/beanResolver"));
}
@Test
public void addsAuthenticationPrincipalResolver() throws InterruptedException {
loadConfig(SockJsSecurityConfig.class);
@ -594,6 +603,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpDestMatchers("/permitAll/**").permitAll()
.simpDestMatchers("/beanResolver/**").access("@security.check()")
.anyMessage().denyAll();
}
// @formatter:on
@ -613,6 +623,20 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
public TestHandshakeHandler testHandshakeHandler() {
return new TestHandshakeHandler();
}
@Bean
public SecurityCheck security() {
return new SecurityCheck();
}
static class SecurityCheck {
private boolean check;
public boolean check() {
check = !check;
return check;
}
}
}
@Configuration