mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-15 23:25:04 +00:00
WebSocketMessageBrokerConfigTests groovy->java
Of note is that this commit unrolls three Spock @Unroll-parameterized tests into a separate test for each parameter. Issue: gh-4939
This commit is contained in:
parent
3c07d99b0a
commit
ec46b7dbe1
@ -1,560 +0,0 @@
|
|||||||
package org.springframework.security.config.websocket
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.*
|
|
||||||
|
|
||||||
import org.springframework.beans.BeansException
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition
|
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
|
|
||||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
|
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition
|
|
||||||
import org.springframework.core.MethodParameter
|
|
||||||
import org.springframework.core.task.SyncTaskExecutor
|
|
||||||
import org.springframework.http.server.ServerHttpRequest
|
|
||||||
import org.springframework.http.server.ServerHttpResponse
|
|
||||||
import org.springframework.messaging.Message
|
|
||||||
import org.springframework.messaging.MessageDeliveryException
|
|
||||||
import org.springframework.messaging.handler.annotation.MessageMapping
|
|
||||||
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver
|
|
||||||
import org.springframework.messaging.simp.SimpMessageHeaderAccessor
|
|
||||||
import org.springframework.messaging.simp.SimpMessageType
|
|
||||||
import org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler
|
|
||||||
import org.springframework.messaging.support.ChannelInterceptor
|
|
||||||
import org.springframework.messaging.support.GenericMessage
|
|
||||||
import org.springframework.mock.web.MockHttpServletRequest
|
|
||||||
import org.springframework.mock.web.MockHttpServletResponse
|
|
||||||
import org.springframework.security.access.AccessDeniedException
|
|
||||||
import org.springframework.security.access.expression.SecurityExpressionOperations;
|
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken
|
|
||||||
import org.springframework.security.config.AbstractXmlConfigTests
|
|
||||||
import org.springframework.security.core.Authentication
|
|
||||||
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder
|
|
||||||
import org.springframework.security.messaging.access.expression.DefaultMessageSecurityExpressionHandler;
|
|
||||||
import org.springframework.security.messaging.access.expression.MessageSecurityExpressionRoot;
|
|
||||||
import org.springframework.security.web.csrf.CsrfToken
|
|
||||||
import org.springframework.security.web.csrf.DefaultCsrfToken
|
|
||||||
import org.springframework.security.web.csrf.InvalidCsrfTokenException
|
|
||||||
import org.springframework.stereotype.Controller
|
|
||||||
import org.springframework.util.AntPathMatcher
|
|
||||||
import org.springframework.web.servlet.HandlerMapping
|
|
||||||
import org.springframework.web.socket.WebSocketHandler
|
|
||||||
import org.springframework.web.socket.server.HandshakeFailureException
|
|
||||||
import org.springframework.web.socket.server.HandshakeHandler
|
|
||||||
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor
|
|
||||||
import org.springframework.web.socket.server.support.WebSocketHttpRequestHandler
|
|
||||||
import org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler
|
|
||||||
import org.springframework.web.socket.sockjs.transport.handler.SockJsWebSocketHandler
|
|
||||||
|
|
||||||
import spock.lang.Unroll
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Rob Winch
|
|
||||||
*/
|
|
||||||
class WebSocketMessageBrokerConfigTests extends AbstractXmlConfigTests {
|
|
||||||
Authentication messageUser = new TestingAuthenticationToken('user','pass','ROLE_USER')
|
|
||||||
boolean useSockJS = false
|
|
||||||
CsrfToken csrfToken = new DefaultCsrfToken('headerName', 'paramName', 'token')
|
|
||||||
|
|
||||||
def cleanup() {
|
|
||||||
SecurityContextHolder.clearContext()
|
|
||||||
}
|
|
||||||
|
|
||||||
def 'websocket with no id automatically integrates with clientInboundChannel'() {
|
|
||||||
setup:
|
|
||||||
websocket {
|
|
||||||
'intercept-message'(pattern:'/permitAll',access:'permitAll')
|
|
||||||
'intercept-message'(pattern:'/denyAll',access:'denyAll')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
when: 'message is sent to the denyAll endpoint'
|
|
||||||
clientInboundChannel.send(message('/denyAll'))
|
|
||||||
|
|
||||||
then: 'access is denied to the denyAll endpoint'
|
|
||||||
def e = thrown(MessageDeliveryException)
|
|
||||||
e.cause instanceof AccessDeniedException
|
|
||||||
|
|
||||||
and: 'access is granted to the permitAll endpoint'
|
|
||||||
clientInboundChannel.send(message('/permitAll'))
|
|
||||||
}
|
|
||||||
|
|
||||||
def 'anonymous authentication supported'() {
|
|
||||||
setup:
|
|
||||||
websocket {
|
|
||||||
'intercept-message'(pattern:'/permitAll',access:'permitAll')
|
|
||||||
'intercept-message'(pattern:'/denyAll',access:'denyAll')
|
|
||||||
}
|
|
||||||
messageUser = null
|
|
||||||
|
|
||||||
when: 'message is sent to the permitAll endpoint with no user'
|
|
||||||
clientInboundChannel.send(message('/permitAll'))
|
|
||||||
|
|
||||||
then: 'access is granted'
|
|
||||||
noExceptionThrown()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Unroll
|
|
||||||
def "message type - #type"(SimpMessageType type) {
|
|
||||||
setup:
|
|
||||||
websocket {
|
|
||||||
'intercept-message'('type': type.toString(), access:'permitAll')
|
|
||||||
'intercept-message'(pattern:'/**', access:'denyAll')
|
|
||||||
}
|
|
||||||
messageUser = null
|
|
||||||
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(type)
|
|
||||||
if(SimpMessageType.CONNECT == type) {
|
|
||||||
headers.setNativeHeader(csrfToken.headerName, csrfToken.token)
|
|
||||||
}
|
|
||||||
Message message = message(headers, '/permitAll')
|
|
||||||
|
|
||||||
when: 'message is sent to the permitAll endpoint with no user'
|
|
||||||
clientInboundChannel.send(message)
|
|
||||||
|
|
||||||
then: 'access is granted'
|
|
||||||
noExceptionThrown()
|
|
||||||
|
|
||||||
where:
|
|
||||||
type << SimpMessageType.values()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Unroll
|
|
||||||
def "pattern and message type - #type"(SimpMessageType type) {
|
|
||||||
setup:
|
|
||||||
websocket {
|
|
||||||
'intercept-message'(pattern: '/permitAll', 'type': type.toString(), access:'permitAll')
|
|
||||||
'intercept-message'(pattern:'/**', access:'denyAll')
|
|
||||||
}
|
|
||||||
|
|
||||||
when: 'message is sent to the permitAll endpoint with no user'
|
|
||||||
clientInboundChannel.send(message('/permitAll', type))
|
|
||||||
|
|
||||||
then: 'access is granted'
|
|
||||||
noExceptionThrown()
|
|
||||||
|
|
||||||
when: 'message sent to other message type'
|
|
||||||
clientInboundChannel.send(message('/permitAll', SimpMessageType.UNSUBSCRIBE))
|
|
||||||
|
|
||||||
then: 'does not match'
|
|
||||||
MessageDeliveryException e = thrown()
|
|
||||||
e.cause instanceof AccessDeniedException
|
|
||||||
|
|
||||||
when: 'message is sent to other pattern'
|
|
||||||
clientInboundChannel.send(message('/other', type))
|
|
||||||
|
|
||||||
then: 'does not match'
|
|
||||||
MessageDeliveryException eOther = thrown()
|
|
||||||
eOther.cause instanceof AccessDeniedException
|
|
||||||
|
|
||||||
where:
|
|
||||||
type << [SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE]
|
|
||||||
}
|
|
||||||
|
|
||||||
@Unroll
|
|
||||||
def "intercept-message with invalid type and pattern - #type"(SimpMessageType type) {
|
|
||||||
when:
|
|
||||||
websocket {
|
|
||||||
'intercept-message'(pattern : '/**', 'type': type.toString(), access:'permitAll')
|
|
||||||
}
|
|
||||||
then:
|
|
||||||
thrown(BeanDefinitionParsingException)
|
|
||||||
|
|
||||||
where:
|
|
||||||
type << [SimpMessageType.CONNECT, SimpMessageType.CONNECT_ACK, SimpMessageType.DISCONNECT, SimpMessageType.DISCONNECT_ACK, SimpMessageType.HEARTBEAT, SimpMessageType.OTHER, SimpMessageType.UNSUBSCRIBE ]
|
|
||||||
}
|
|
||||||
|
|
||||||
def 'messages with no id automatically adds Authentication argument resolver'() {
|
|
||||||
setup:
|
|
||||||
def id = 'authenticationController'
|
|
||||||
bean(id,MyController)
|
|
||||||
bean('inPostProcessor',InboundExecutorPostProcessor)
|
|
||||||
websocket {
|
|
||||||
'intercept-message'(pattern:'/**',access:'permitAll')
|
|
||||||
}
|
|
||||||
|
|
||||||
when: 'message is sent to the authentication endpoint'
|
|
||||||
clientInboundChannel.send(message('/authentication'))
|
|
||||||
|
|
||||||
then: 'the AuthenticationPrincipal is resolved'
|
|
||||||
def controller = appContext.getBean(id)
|
|
||||||
controller.authenticationPrincipal == messageUser.name
|
|
||||||
}
|
|
||||||
|
|
||||||
def 'messages of type CONNECT use CsrfTokenHandshakeInterceptor'() {
|
|
||||||
setup:
|
|
||||||
def id = 'authenticationController'
|
|
||||||
bean(id,MyController)
|
|
||||||
bean('inPostProcessor',InboundExecutorPostProcessor)
|
|
||||||
websocket {
|
|
||||||
'intercept-message'(pattern:'/**',access:'permitAll')
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT)
|
|
||||||
Message<?> message = message(headers,'/authentication')
|
|
||||||
WebSocketHttpRequestHandler handler = appContext.getBean(WebSocketHttpRequestHandler)
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest()
|
|
||||||
String sessionAttr = "sessionAttr"
|
|
||||||
request.getSession().setAttribute(sessionAttr,"sessionValue")
|
|
||||||
|
|
||||||
CsrfToken token = new DefaultCsrfToken("header", "param", "token")
|
|
||||||
request.setAttribute(CsrfToken.name, token)
|
|
||||||
|
|
||||||
when:
|
|
||||||
handler.handleRequest(request , new MockHttpServletResponse())
|
|
||||||
TestHandshakeHandler handshakeHandler = appContext.getBean(TestHandshakeHandler)
|
|
||||||
|
|
||||||
then: 'CsrfToken is populated'
|
|
||||||
handshakeHandler.attributes.get(CsrfToken.name) == token
|
|
||||||
|
|
||||||
and: 'Explicitly listed HandshakeInterceptor are not overridden'
|
|
||||||
handshakeHandler.attributes.get(sessionAttr) == request.getSession().getAttribute(sessionAttr)
|
|
||||||
}
|
|
||||||
|
|
||||||
def 'messages of type CONNECT use CsrfTokenHandshakeInterceptor with SockJS'() {
|
|
||||||
setup:
|
|
||||||
useSockJS = true
|
|
||||||
def id = 'authenticationController'
|
|
||||||
bean(id,MyController)
|
|
||||||
bean('inPostProcessor',InboundExecutorPostProcessor)
|
|
||||||
websocket {
|
|
||||||
'intercept-message'(pattern:'/**',access:'permitAll')
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT)
|
|
||||||
Message<?> message = message(headers,'/authentication')
|
|
||||||
SockJsHttpRequestHandler handler = appContext.getBean(SockJsHttpRequestHandler)
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest()
|
|
||||||
String sessionAttr = "sessionAttr"
|
|
||||||
request.getSession().setAttribute(sessionAttr,"sessionValue")
|
|
||||||
|
|
||||||
CsrfToken token = new DefaultCsrfToken("header", "param", "token")
|
|
||||||
request.setAttribute(CsrfToken.name, token)
|
|
||||||
|
|
||||||
request.setMethod("GET")
|
|
||||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/289/tpyx6mde/websocket")
|
|
||||||
|
|
||||||
when:
|
|
||||||
handler.handleRequest(request , new MockHttpServletResponse())
|
|
||||||
TestHandshakeHandler handshakeHandler = appContext.getBean(TestHandshakeHandler)
|
|
||||||
|
|
||||||
then: 'CsrfToken is populated'
|
|
||||||
handshakeHandler.attributes?.get(CsrfToken.name) == token
|
|
||||||
|
|
||||||
and: 'Explicitly listed HandshakeInterceptor are not overridden'
|
|
||||||
handshakeHandler.attributes?.get(sessionAttr) == request.getSession().getAttribute(sessionAttr)
|
|
||||||
}
|
|
||||||
|
|
||||||
def 'messages of type CONNECT require valid CsrfToken'() {
|
|
||||||
setup:
|
|
||||||
def id = 'authenticationController'
|
|
||||||
bean(id,MyController)
|
|
||||||
bean('inPostProcessor',InboundExecutorPostProcessor)
|
|
||||||
websocket {
|
|
||||||
'intercept-message'(pattern:'/**',access:'permitAll')
|
|
||||||
}
|
|
||||||
|
|
||||||
when: 'websocket of type CONNECTION is sent without CsrfTOken'
|
|
||||||
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT)
|
|
||||||
Message<?> message = message(headers,'/authentication')
|
|
||||||
clientInboundChannel.send(message)
|
|
||||||
|
|
||||||
then: 'CSRF Protection blocks the Message'
|
|
||||||
MessageDeliveryException expected = thrown()
|
|
||||||
expected.cause instanceof InvalidCsrfTokenException
|
|
||||||
}
|
|
||||||
|
|
||||||
def 'messages of type CONNECT disabled valid CsrfToken'() {
|
|
||||||
setup:
|
|
||||||
def id = 'authenticationController'
|
|
||||||
bean(id,MyController)
|
|
||||||
bean('inPostProcessor',InboundExecutorPostProcessor)
|
|
||||||
websocket('same-origin-disabled':true) {
|
|
||||||
'intercept-message'(pattern:'/**',access:'permitAll')
|
|
||||||
}
|
|
||||||
|
|
||||||
when: 'websocket of type CONNECTION is sent without CsrfTOken'
|
|
||||||
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT)
|
|
||||||
Message<?> message = message(headers,'/authentication')
|
|
||||||
clientInboundChannel.send(message)
|
|
||||||
|
|
||||||
then: 'CSRF Protection blocks the Message'
|
|
||||||
noExceptionThrown()
|
|
||||||
}
|
|
||||||
|
|
||||||
def 'websocket with no id does not override customArgumentResolvers'() {
|
|
||||||
setup:
|
|
||||||
def id = 'authenticationController'
|
|
||||||
bean(id,MyController)
|
|
||||||
bean('inPostProcessor',InboundExecutorPostProcessor)
|
|
||||||
bean('mcar', MyCustomArgumentResolver)
|
|
||||||
xml.'websocket:message-broker' {
|
|
||||||
'websocket:transport' {}
|
|
||||||
'websocket:stomp-endpoint'(path:'/app') {
|
|
||||||
'websocket:handshake-handler'(ref:'testHandler') {}
|
|
||||||
}
|
|
||||||
'websocket:simple-broker'(prefix:"/queue, /topic"){}
|
|
||||||
'websocket:argument-resolvers' {
|
|
||||||
'b:ref'(bean:'mcar')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
websocket {
|
|
||||||
'intercept-message'(pattern:'/**',access:'permitAll')
|
|
||||||
}
|
|
||||||
|
|
||||||
when: 'websocket is sent to the myCustom endpoint'
|
|
||||||
clientInboundChannel.send(message('/myCustom'))
|
|
||||||
|
|
||||||
then: 'myCustomArgument is resolved'
|
|
||||||
def controller = appContext.getBean(id)
|
|
||||||
controller.myCustomArgument!= null
|
|
||||||
}
|
|
||||||
|
|
||||||
def 'websocket defaults pathMatcher'() {
|
|
||||||
setup:
|
|
||||||
bean('pathMatcher',AntPathMatcher.name,['.'])
|
|
||||||
bean('testHandler', TestHandshakeHandler)
|
|
||||||
xml.'websocket:message-broker'('path-matcher':'pathMatcher') {
|
|
||||||
'websocket:transport' {}
|
|
||||||
'websocket:stomp-endpoint'(path:'/app') {
|
|
||||||
'websocket:handshake-handler'(ref:'testHandler') {}
|
|
||||||
}
|
|
||||||
'websocket:simple-broker'(prefix:"/queue, /topic"){}
|
|
||||||
}
|
|
||||||
xml.'websocket-message-broker' {
|
|
||||||
'intercept-message'(pattern:'/denyAll.*',access:'denyAll')
|
|
||||||
}
|
|
||||||
createAppContext()
|
|
||||||
|
|
||||||
when: 'sent to denyAll.a'
|
|
||||||
appContext.getBean(SimpAnnotationMethodMessageHandler)
|
|
||||||
clientInboundChannel.send(message('/denyAll.a'))
|
|
||||||
|
|
||||||
then: 'access is denied'
|
|
||||||
MessageDeliveryException expected = thrown()
|
|
||||||
expected.cause instanceof AccessDeniedException
|
|
||||||
|
|
||||||
when: 'sent to denyAll.a.b'
|
|
||||||
clientInboundChannel.send(message('/denyAll.a.b'))
|
|
||||||
|
|
||||||
then: 'access is allowed'
|
|
||||||
noExceptionThrown()
|
|
||||||
}
|
|
||||||
|
|
||||||
def 'websocket with id does not integrate with clientInboundChannel'() {
|
|
||||||
setup:
|
|
||||||
websocket([id:'inCsi']) {
|
|
||||||
'intercept-message'(pattern:'/**',access:'denyAll')
|
|
||||||
}
|
|
||||||
|
|
||||||
when:
|
|
||||||
def success = clientInboundChannel.send(message('/denyAll'))
|
|
||||||
|
|
||||||
then:
|
|
||||||
success
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
def 'websocket with id can be explicitly integrated with clientInboundChannel'() {
|
|
||||||
setup: 'websocket security explicitly setup'
|
|
||||||
xml.'websocket:message-broker' {
|
|
||||||
'websocket:transport' {}
|
|
||||||
'websocket:stomp-endpoint'(path:'/app') {
|
|
||||||
'websocket:sockjs' {}
|
|
||||||
}
|
|
||||||
'websocket:simple-broker'(prefix:"/queue, /topic"){}
|
|
||||||
'websocket:client-inbound-channel' {
|
|
||||||
'websocket:interceptors' {
|
|
||||||
'b:bean'(class:'org.springframework.security.messaging.context.SecurityContextChannelInterceptor'){}
|
|
||||||
'b:ref'(bean:'inCsi'){}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xml.'websocket-message-broker'(id:'inCsi') {
|
|
||||||
'intercept-message'(pattern:'/**',access:'denyAll')
|
|
||||||
}
|
|
||||||
createAppContext()
|
|
||||||
|
|
||||||
when:
|
|
||||||
clientInboundChannel.send(message('/denyAll'))
|
|
||||||
|
|
||||||
then:
|
|
||||||
def e = thrown(MessageDeliveryException)
|
|
||||||
e.cause instanceof AccessDeniedException
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
def 'automatic integration with clientInboundChannel does not override exisiting websocket:interceptors'() {
|
|
||||||
setup:
|
|
||||||
mockBean(ChannelInterceptor,'mci')
|
|
||||||
xml.'websocket:message-broker'('application-destination-prefix':'/app',
|
|
||||||
'user-destination-prefix':'/user') {
|
|
||||||
'websocket:transport' {}
|
|
||||||
'websocket:stomp-endpoint'(path:'/foo') {
|
|
||||||
'websocket:sockjs' {}
|
|
||||||
}
|
|
||||||
'websocket:simple-broker'(prefix:"/queue, /topic"){}
|
|
||||||
'websocket:client-inbound-channel' {
|
|
||||||
'websocket:interceptors' {
|
|
||||||
'b:ref'(bean:'mci'){}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xml.'websocket-message-broker' {
|
|
||||||
'intercept-message'(pattern:'/denyAll',access:'denyAll')
|
|
||||||
'intercept-message'(pattern:'/permitAll',access:'permitAll')
|
|
||||||
}
|
|
||||||
createAppContext()
|
|
||||||
ChannelInterceptor mci = appContext.getBean('mci')
|
|
||||||
when:
|
|
||||||
Message<?> message = message('/permitAll')
|
|
||||||
clientInboundChannel.send(message)
|
|
||||||
|
|
||||||
then:
|
|
||||||
verify(mci).preSend(message, clientInboundChannel) || true
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
def websocket(Map<String,Object> attrs=[:], Closure c) {
|
|
||||||
bean('testHandler', TestHandshakeHandler)
|
|
||||||
xml.'websocket:message-broker' {
|
|
||||||
'websocket:transport' {}
|
|
||||||
'websocket:stomp-endpoint'(path:'/app') {
|
|
||||||
'websocket:handshake-handler'(ref:'testHandler') {}
|
|
||||||
'websocket:handshake-interceptors' {
|
|
||||||
'b:bean'('class':HttpSessionHandshakeInterceptor.name) {}
|
|
||||||
}
|
|
||||||
if(useSockJS) {
|
|
||||||
'websocket:sockjs' {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'websocket:simple-broker'(prefix:"/queue, /topic"){}
|
|
||||||
}
|
|
||||||
xml.'websocket-message-broker'(attrs, c)
|
|
||||||
createAppContext()
|
|
||||||
}
|
|
||||||
|
|
||||||
def 'custom expressions'() {
|
|
||||||
setup:
|
|
||||||
bean('expressionHandler', DenyRobMessageSecurityExpressionHandler)
|
|
||||||
websocket {
|
|
||||||
'expression-handler' (ref: 'expressionHandler') {}
|
|
||||||
'intercept-message'(pattern:'/**',access:'denyRob()')
|
|
||||||
}
|
|
||||||
|
|
||||||
when: 'message is sent with user'
|
|
||||||
clientInboundChannel.send(message('/message'))
|
|
||||||
|
|
||||||
then: 'access is allowed to custom expression'
|
|
||||||
noExceptionThrown()
|
|
||||||
|
|
||||||
when:
|
|
||||||
messageUser = new TestingAuthenticationToken('rob', 'pass', 'ROLE_USER')
|
|
||||||
clientInboundChannel.send(message('/message'))
|
|
||||||
|
|
||||||
then:
|
|
||||||
def e = thrown(MessageDeliveryException)
|
|
||||||
e.cause instanceof AccessDeniedException
|
|
||||||
}
|
|
||||||
|
|
||||||
def getClientInboundChannel() {
|
|
||||||
appContext.getBean("clientInboundChannel")
|
|
||||||
}
|
|
||||||
|
|
||||||
def message(String destination, SimpMessageType type=SimpMessageType.MESSAGE) {
|
|
||||||
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(type)
|
|
||||||
message(headers, destination)
|
|
||||||
}
|
|
||||||
|
|
||||||
def message(SimpMessageHeaderAccessor headers, String destination) {
|
|
||||||
headers.sessionId = '123'
|
|
||||||
headers.sessionAttributes = [:]
|
|
||||||
headers.destination = destination
|
|
||||||
if(messageUser != null) {
|
|
||||||
headers.user = messageUser
|
|
||||||
}
|
|
||||||
if(csrfToken != null) {
|
|
||||||
headers.sessionAttributes[CsrfToken.name] = csrfToken
|
|
||||||
}
|
|
||||||
new GenericMessage<String>("hi",headers.messageHeaders)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
static class MyController {
|
|
||||||
String authenticationPrincipal
|
|
||||||
MyCustomArgument myCustomArgument
|
|
||||||
|
|
||||||
@MessageMapping('/authentication')
|
|
||||||
public void authentication(@AuthenticationPrincipal String un) {
|
|
||||||
this.authenticationPrincipal = un
|
|
||||||
}
|
|
||||||
|
|
||||||
@MessageMapping('/myCustom')
|
|
||||||
public void myCustom(MyCustomArgument myCustomArgument) {
|
|
||||||
this.myCustomArgument = myCustomArgument
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class MyCustomArgument {
|
|
||||||
MyCustomArgument(String notDefaultConstr) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class MyCustomArgumentResolver implements HandlerMethodArgumentResolver {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean supportsParameter(MethodParameter parameter) {
|
|
||||||
parameter.parameterType.isAssignableFrom(MyCustomArgument)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Object resolveArgument(MethodParameter parameter, Message<?> message) throws Exception {
|
|
||||||
new MyCustomArgument("")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class TestHandshakeHandler implements HandshakeHandler {
|
|
||||||
Map<String, Object> attributes;
|
|
||||||
|
|
||||||
boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws HandshakeFailureException {
|
|
||||||
this.attributes = attributes
|
|
||||||
if(wsHandler instanceof SockJsWebSocketHandler) {
|
|
||||||
// work around SPR-12716
|
|
||||||
SockJsWebSocketHandler sockJs = (SockJsWebSocketHandler) wsHandler;
|
|
||||||
this.attributes = sockJs.sockJsSession.attributes
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the clientInboundChannel Executor to be synchronous
|
|
||||||
*/
|
|
||||||
static class InboundExecutorPostProcessor implements BeanDefinitionRegistryPostProcessor {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
|
|
||||||
BeanDefinition inbound = registry.getBeanDefinition("clientInboundChannel")
|
|
||||||
inbound.getConstructorArgumentValues().addIndexedArgumentValue(0, new RootBeanDefinition(SyncTaskExecutor));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DenyRobMessageSecurityExpressionHandler extends DefaultMessageSecurityExpressionHandler<Object> {
|
|
||||||
@Override
|
|
||||||
protected SecurityExpressionOperations createSecurityExpressionRoot(
|
|
||||||
Authentication authentication,
|
|
||||||
Message<Object> invocation) {
|
|
||||||
return new MessageSecurityExpressionRoot(authentication, invocation) {
|
|
||||||
public boolean denyRob() {
|
|
||||||
Authentication auth = getAuthentication();
|
|
||||||
return auth != null && !"rob".equals(auth.getName());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,547 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://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.websocket;
|
||||||
|
|
||||||
|
import org.assertj.core.api.ThrowableAssert;
|
||||||
|
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
|
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||||
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
|
import org.springframework.core.MethodParameter;
|
||||||
|
import org.springframework.core.task.SyncTaskExecutor;
|
||||||
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
|
import org.springframework.messaging.Message;
|
||||||
|
import org.springframework.messaging.MessageChannel;
|
||||||
|
import org.springframework.messaging.handler.annotation.MessageMapping;
|
||||||
|
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
|
||||||
|
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
|
||||||
|
import org.springframework.messaging.simp.SimpMessageType;
|
||||||
|
import org.springframework.messaging.support.ChannelInterceptorAdapter;
|
||||||
|
import org.springframework.messaging.support.GenericMessage;
|
||||||
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
import org.springframework.security.access.expression.SecurityExpressionOperations;
|
||||||
|
import org.springframework.security.config.test.SpringTestRule;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.messaging.access.expression.DefaultMessageSecurityExpressionHandler;
|
||||||
|
import org.springframework.security.messaging.access.expression.MessageSecurityExpressionRoot;
|
||||||
|
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
|
||||||
|
import org.springframework.security.test.context.support.WithMockUser;
|
||||||
|
import org.springframework.security.web.csrf.CsrfToken;
|
||||||
|
import org.springframework.security.web.csrf.DefaultCsrfToken;
|
||||||
|
import org.springframework.security.web.csrf.InvalidCsrfTokenException;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
|
import org.springframework.web.socket.server.HandshakeFailureException;
|
||||||
|
import org.springframework.web.socket.server.HandshakeHandler;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.*;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Rob Winch
|
||||||
|
* @author Josh Cummings
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@SecurityTestExecutionListeners
|
||||||
|
public class WebSocketMessageBrokerConfigTests {
|
||||||
|
private static final String CONFIG_LOCATION_PREFIX =
|
||||||
|
"classpath:org/springframework/security/config/websocket/WebSocketMessageBrokerConfigTests";
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final SpringTestRule spring = new SpringTestRule();
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private MessageChannel clientInboundChannel;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private MessageController messageController;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private MessageWithArgumentController messageWithArgumentController;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private TestHandshakeHandler testHandshakeHandler;
|
||||||
|
|
||||||
|
private CsrfToken token = new DefaultCsrfToken("header", "param", "token");
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenNoIdSpecifiedThenIntegratesWithClientInboundChannel() {
|
||||||
|
this.spring.configLocations(xml("NoIdConfig")).autowire();
|
||||||
|
|
||||||
|
this.clientInboundChannel.send(message("/permitAll"));
|
||||||
|
|
||||||
|
assertThatThrownBy(() -> this.clientInboundChannel.send(message("/denyAll")))
|
||||||
|
.hasCauseInstanceOf(AccessDeniedException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenAnonymousMessageWithConnectMessageTypeThenPermitted() {
|
||||||
|
this.spring.configLocations(xml("NoIdConfig")).autowire();
|
||||||
|
|
||||||
|
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT);
|
||||||
|
headers.setNativeHeader(this.token.getHeaderName(), this.token.getToken());
|
||||||
|
|
||||||
|
assertThatCode(() -> this.clientInboundChannel.send(message("/permitAll", headers)))
|
||||||
|
.doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenAnonymousMessageWithConnectAckMessageTypeThenPermitted() {
|
||||||
|
this.spring.configLocations(xml("NoIdConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/permitAll", SimpMessageType.CONNECT_ACK);
|
||||||
|
|
||||||
|
assertThatCode(send(message)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenAnonymousMessageWithDisconnectMessageTypeThenPermitted() {
|
||||||
|
this.spring.configLocations(xml("NoIdConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/permitAll", SimpMessageType.DISCONNECT);
|
||||||
|
|
||||||
|
assertThatCode(send(message)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenAnonymousMessageWithDisconnectAckMessageTypeThenPermitted() {
|
||||||
|
this.spring.configLocations(xml("NoIdConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/permitAll", SimpMessageType.DISCONNECT_ACK);
|
||||||
|
|
||||||
|
assertThatCode(send(message)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenAnonymousMessageWithHeartbeatMessageTypeThenPermitted() {
|
||||||
|
this.spring.configLocations(xml("NoIdConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/permitAll", SimpMessageType.HEARTBEAT);
|
||||||
|
|
||||||
|
assertThatCode(send(message)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenAnonymousMessageWithMessageMessageTypeThenPermitted() {
|
||||||
|
this.spring.configLocations(xml("NoIdConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/permitAll", SimpMessageType.MESSAGE);
|
||||||
|
|
||||||
|
assertThatCode(send(message)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenAnonymousMessageWithOtherMessageTypeThenPermitted() {
|
||||||
|
this.spring.configLocations(xml("NoIdConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/permitAll", SimpMessageType.OTHER);
|
||||||
|
|
||||||
|
assertThatCode(send(message)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenAnonymousMessageWithSubscribeMessageTypeThenPermitted() {
|
||||||
|
this.spring.configLocations(xml("NoIdConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/permitAll", SimpMessageType.SUBSCRIBE);
|
||||||
|
|
||||||
|
assertThatCode(send(message)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenAnonymousMessageWithUnsubscribeMessageTypeThenPermitted() {
|
||||||
|
this.spring.configLocations(xml("NoIdConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/permitAll", SimpMessageType.UNSUBSCRIBE);
|
||||||
|
|
||||||
|
assertThatCode(send(message)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenConnectWithoutCsrfTokenThenDenied() {
|
||||||
|
this.spring.configLocations(xml("SyncConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/message", SimpMessageType.CONNECT);
|
||||||
|
|
||||||
|
assertThatThrownBy(send(message)).hasCauseInstanceOf(InvalidCsrfTokenException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenConnectWithSameOriginDisabledThenCsrfTokenNotRequired() {
|
||||||
|
this.spring.configLocations(xml("SyncSameOriginDisabledConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/message", SimpMessageType.CONNECT);
|
||||||
|
|
||||||
|
assertThatCode(send(message)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenInterceptWiredForMessageTypeThenDeniesOnTypeMismatch() {
|
||||||
|
this.spring.configLocations(xml("MessageInterceptTypeConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/permitAll", SimpMessageType.MESSAGE);
|
||||||
|
|
||||||
|
assertThatCode(send(message)).doesNotThrowAnyException();
|
||||||
|
|
||||||
|
message = message("/permitAll", SimpMessageType.UNSUBSCRIBE);
|
||||||
|
|
||||||
|
assertThatThrownBy(send(message)).hasCauseInstanceOf(AccessDeniedException.class);
|
||||||
|
|
||||||
|
message = message("/anyOther", SimpMessageType.MESSAGE);
|
||||||
|
|
||||||
|
assertThatThrownBy(send(message)).hasCauseInstanceOf(AccessDeniedException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenInterceptWiredForSubscribeTypeThenDeniesOnTypeMismatch() {
|
||||||
|
this.spring.configLocations(xml("SubscribeInterceptTypeConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/permitAll", SimpMessageType.SUBSCRIBE);
|
||||||
|
|
||||||
|
assertThatCode(send(message)).doesNotThrowAnyException();
|
||||||
|
|
||||||
|
message = message("/permitAll", SimpMessageType.UNSUBSCRIBE);
|
||||||
|
|
||||||
|
assertThatThrownBy(send(message)).hasCauseInstanceOf(AccessDeniedException.class);
|
||||||
|
|
||||||
|
message = message("/anyOther", SimpMessageType.SUBSCRIBE);
|
||||||
|
|
||||||
|
assertThatThrownBy(send(message)).hasCauseInstanceOf(AccessDeniedException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- invalid intercept types -- //
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void configureWhenUsingConnectMessageTypeThenAutowireFails() {
|
||||||
|
ThrowingCallable bad = () ->
|
||||||
|
this.spring.configLocations(xml("ConnectInterceptTypeConfig")).autowire();
|
||||||
|
|
||||||
|
assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void configureWhenUsingConnectAckMessageTypeThenAutowireFails() {
|
||||||
|
ThrowingCallable bad = () ->
|
||||||
|
this.spring.configLocations(xml("ConnectAckInterceptTypeConfig")).autowire();
|
||||||
|
|
||||||
|
assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void configureWhenUsingDisconnectMessageTypeThenAutowireFails() {
|
||||||
|
ThrowingCallable bad = () ->
|
||||||
|
this.spring.configLocations(xml("DisconnectInterceptTypeConfig")).autowire();
|
||||||
|
|
||||||
|
assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void configureWhenUsingDisconnectAckMessageTypeThenAutowireFails() {
|
||||||
|
ThrowingCallable bad = () ->
|
||||||
|
this.spring.configLocations(xml("DisconnectAckInterceptTypeConfig")).autowire();
|
||||||
|
|
||||||
|
assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void configureWhenUsingHeartbeatMessageTypeThenAutowireFails() {
|
||||||
|
ThrowingCallable bad = () ->
|
||||||
|
this.spring.configLocations(xml("HeartbeatInterceptTypeConfig")).autowire();
|
||||||
|
|
||||||
|
assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void configureWhenUsingOtherMessageTypeThenAutowireFails() {
|
||||||
|
ThrowingCallable bad = () ->
|
||||||
|
this.spring.configLocations(xml("OtherInterceptTypeConfig")).autowire();
|
||||||
|
|
||||||
|
assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void configureWhenUsingUnsubscribeMessageTypeThenAutowireFails() {
|
||||||
|
ThrowingCallable bad = () ->
|
||||||
|
this.spring.configLocations(xml("UnsubscribeInterceptTypeConfig")).autowire();
|
||||||
|
|
||||||
|
assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenNoIdMessageThenAuthenticationPrincipalResolved() throws Exception {
|
||||||
|
this.spring.configLocations(xml("SyncConfig")).autowire();
|
||||||
|
|
||||||
|
this.clientInboundChannel.send(message("/message"));
|
||||||
|
|
||||||
|
assertThat(this.messageController.username).isEqualTo("anonymous");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void requestWhenConnectMessageThenUsesCsrfTokenHandshakeInterceptor() throws Exception {
|
||||||
|
this.spring.configLocations(xml("SyncConfig")).autowire();
|
||||||
|
|
||||||
|
WebApplicationContext context = (WebApplicationContext) this.spring.getContext();
|
||||||
|
MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).build();
|
||||||
|
|
||||||
|
String csrfAttributeName = CsrfToken.class.getName();
|
||||||
|
String customAttributeName = this.getClass().getName();
|
||||||
|
|
||||||
|
MvcResult result = mvc.perform(get("/app")
|
||||||
|
.requestAttr(csrfAttributeName, this.token)
|
||||||
|
.sessionAttr(customAttributeName, "attributeValue"))
|
||||||
|
.andReturn();
|
||||||
|
|
||||||
|
CsrfToken handshakeToken = (CsrfToken) this.testHandshakeHandler.attributes.get(csrfAttributeName);
|
||||||
|
String handshakeValue = (String) this.testHandshakeHandler.attributes.get(customAttributeName);
|
||||||
|
String sessionValue = (String) result.getRequest().getSession().getAttribute(customAttributeName);
|
||||||
|
|
||||||
|
assertThat(handshakeToken).isEqualTo(this.token)
|
||||||
|
.withFailMessage("CsrfToken is populated");
|
||||||
|
|
||||||
|
assertThat(handshakeValue).isEqualTo(sessionValue)
|
||||||
|
.withFailMessage("Explicitly listed session variables are not overridden");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void requestWhenConnectMessageAndUsingSockJsThenUsesCsrfTokenHandshakeInterceptor() throws Exception {
|
||||||
|
this.spring.configLocations(xml("SyncSockJsConfig")).autowire();
|
||||||
|
|
||||||
|
WebApplicationContext context = (WebApplicationContext) this.spring.getContext();
|
||||||
|
MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).build();
|
||||||
|
|
||||||
|
String csrfAttributeName = CsrfToken.class.getName();
|
||||||
|
String customAttributeName = this.getClass().getName();
|
||||||
|
|
||||||
|
MvcResult result = mvc.perform(get("/app/289/tpyx6mde/websocket")
|
||||||
|
.requestAttr(csrfAttributeName, this.token)
|
||||||
|
.sessionAttr(customAttributeName, "attributeValue"))
|
||||||
|
.andReturn();
|
||||||
|
|
||||||
|
CsrfToken handshakeToken = (CsrfToken) this.testHandshakeHandler.attributes.get(csrfAttributeName);
|
||||||
|
String handshakeValue = (String) this.testHandshakeHandler.attributes.get(customAttributeName);
|
||||||
|
String sessionValue = (String) result.getRequest().getSession().getAttribute(customAttributeName);
|
||||||
|
|
||||||
|
assertThat(handshakeToken).isEqualTo(this.token)
|
||||||
|
.withFailMessage("CsrfToken is populated");
|
||||||
|
|
||||||
|
assertThat(handshakeValue).isEqualTo(sessionValue)
|
||||||
|
.withFailMessage("Explicitly listed session variables are not overridden");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenNoIdSpecifiedThenCustomArgumentResolversAreNotOverridden() {
|
||||||
|
this.spring.configLocations(xml("SyncCustomArgumentResolverConfig")).autowire();
|
||||||
|
|
||||||
|
this.clientInboundChannel.send(message("/message-with-argument"));
|
||||||
|
|
||||||
|
assertThat(this.messageWithArgumentController.messageArgument).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenUsingCustomPathMatcherThenSecurityAppliesIt() {
|
||||||
|
this.spring.configLocations(xml("CustomPathMatcherConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/denyAll.a");
|
||||||
|
|
||||||
|
assertThatThrownBy(send(message)).hasCauseInstanceOf(AccessDeniedException.class);
|
||||||
|
|
||||||
|
message = message("/denyAll.a.b");
|
||||||
|
|
||||||
|
assertThatCode(send(message)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenIdSpecifiedThenSecurityDoesNotIntegrateWithClientInboundChannel() {
|
||||||
|
this.spring.configLocations(xml("IdConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/denyAll");
|
||||||
|
|
||||||
|
assertThatCode(send(message)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser
|
||||||
|
public void sendWhenIdSpecifiedAndExplicitlyIntegratedWhenBrokerUsesClientInboundChannel() {
|
||||||
|
this.spring.configLocations(xml("IdIntegratedConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/denyAll");
|
||||||
|
|
||||||
|
assertThatThrownBy(send(message)).hasCauseInstanceOf(AccessDeniedException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendWhenNoIdSpecifiedThenSecurityDoesntOverrideCustomInterceptors() {
|
||||||
|
this.spring.configLocations(xml("CustomInterceptorConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/throwAll");
|
||||||
|
|
||||||
|
assertThatThrownBy(send(message)).hasCauseInstanceOf(UnsupportedOperationException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "nile")
|
||||||
|
public void sendWhenCustomExpressionHandlerThenAuthorizesAccordingly() {
|
||||||
|
this.spring.configLocations(xml("CustomExpressionHandlerConfig")).autowire();
|
||||||
|
|
||||||
|
Message<?> message = message("/denyNile");
|
||||||
|
|
||||||
|
assertThatThrownBy(send(message)).hasCauseInstanceOf(AccessDeniedException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String xml(String configName) {
|
||||||
|
return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
|
||||||
|
}
|
||||||
|
|
||||||
|
private ThrowableAssert.ThrowingCallable send(Message<?> message) {
|
||||||
|
return () -> this.clientInboundChannel.send(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Message<?> message(String destination) {
|
||||||
|
return message(destination, SimpMessageType.MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Message<?> message(String destination, SimpMessageType type) {
|
||||||
|
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(type);
|
||||||
|
return message(destination, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Message<?> message(String destination, SimpMessageHeaderAccessor headers) {
|
||||||
|
headers.setSessionId("123");
|
||||||
|
headers.setSessionAttributes(new HashMap<>());
|
||||||
|
headers.setDestination(destination);
|
||||||
|
|
||||||
|
if (SecurityContextHolder.getContext().getAuthentication() != null) {
|
||||||
|
headers.setUser(SecurityContextHolder.getContext().getAuthentication());
|
||||||
|
}
|
||||||
|
|
||||||
|
headers.getSessionAttributes().put(CsrfToken.class.getName(), this.token);
|
||||||
|
|
||||||
|
return new GenericMessage<>("hi", headers.getMessageHeaders());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
static class MessageController {
|
||||||
|
String username;
|
||||||
|
|
||||||
|
@MessageMapping("/message")
|
||||||
|
public void authentication(@AuthenticationPrincipal String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
static class MessageWithArgumentController {
|
||||||
|
MessageArgument messageArgument;
|
||||||
|
|
||||||
|
@MessageMapping("/message-with-argument")
|
||||||
|
public void myCustom(MessageArgument messageArgument) {
|
||||||
|
this.messageArgument = messageArgument;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static class MessageArgument {
|
||||||
|
MessageArgument(String notDefaultConstructor) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class MessageArgumentResolver implements HandlerMethodArgumentResolver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsParameter(MethodParameter parameter) {
|
||||||
|
return parameter.getParameterType().isAssignableFrom(MessageArgument.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object resolveArgument(MethodParameter parameter, Message<?> message) throws Exception {
|
||||||
|
return new MessageArgument("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TestHandshakeHandler implements HandshakeHandler {
|
||||||
|
Map<String, Object> attributes;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doHandshake(
|
||||||
|
ServerHttpRequest request,
|
||||||
|
org.springframework.http.server.ServerHttpResponse response,
|
||||||
|
WebSocketHandler wsHandler,
|
||||||
|
Map<String, Object> attributes) throws HandshakeFailureException {
|
||||||
|
|
||||||
|
this.attributes = attributes;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class InboundExecutorPostProcessor implements BeanDefinitionRegistryPostProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
|
||||||
|
BeanDefinition inbound = registry.getBeanDefinition("clientInboundChannel");
|
||||||
|
inbound.getConstructorArgumentValues()
|
||||||
|
.addIndexedArgumentValue(0, new RootBeanDefinition(SyncTaskExecutor.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ExceptingInterceptor extends ChannelInterceptorAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Message<?> preSend(Message<?> message, MessageChannel channel) {
|
||||||
|
throw new UnsupportedOperationException("no");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DenyNileMessageSecurityExpressionHandler
|
||||||
|
extends DefaultMessageSecurityExpressionHandler<Object> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SecurityExpressionOperations createSecurityExpressionRoot(
|
||||||
|
Authentication authentication,
|
||||||
|
Message<Object> invocation) {
|
||||||
|
|
||||||
|
return new MessageSecurityExpressionRoot(authentication, invocation) {
|
||||||
|
public boolean denyNile() {
|
||||||
|
Authentication auth = getAuthentication();
|
||||||
|
return auth != null && !"nile".equals(auth.getName());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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="CONNECT_ACK" access="permitAll"/>
|
||||||
|
<intercept-message pattern="/**" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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="CONNECT" access="permitAll"/>
|
||||||
|
<intercept-message pattern="/**" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,33 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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"/>
|
||||||
|
|
||||||
|
<b:bean name="expressionHandler" class="org.springframework.security.config.websocket.WebSocketMessageBrokerConfigTests.DenyNileMessageSecurityExpressionHandler"/>
|
||||||
|
|
||||||
|
<websocket-message-broker>
|
||||||
|
<expression-handler ref="expressionHandler"/>
|
||||||
|
<intercept-message pattern="/**" access="denyNile()"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,45 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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:websocket="http://www.springframework.org/schema/websocket"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.springframework.org/schema/security"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
|
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
|
||||||
|
|
||||||
|
<websocket:message-broker application-destination-prefix="/app" user-destination-prefix="/user">
|
||||||
|
<websocket:transport/>
|
||||||
|
<websocket:stomp-endpoint path="/foo">
|
||||||
|
<websocket:sockjs/>
|
||||||
|
</websocket:stomp-endpoint>
|
||||||
|
<websocket:simple-broker prefix="/queue, /topic"/>
|
||||||
|
<websocket:client-inbound-channel>
|
||||||
|
<websocket:interceptors>
|
||||||
|
<b:ref bean="eci"/>
|
||||||
|
</websocket:interceptors>
|
||||||
|
</websocket:client-inbound-channel>
|
||||||
|
</websocket:message-broker>
|
||||||
|
|
||||||
|
<b:bean name="eci" class="org.springframework.security.config.websocket.WebSocketMessageBrokerConfigTests.ExceptingInterceptor"/>
|
||||||
|
|
||||||
|
<websocket-message-broker>
|
||||||
|
<intercept-message pattern="/permitAll" access="permitAll"/>
|
||||||
|
<intercept-message pattern="/denyAll" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,46 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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:websocket="http://www.springframework.org/schema/websocket"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.springframework.org/schema/security"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
|
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
|
||||||
|
|
||||||
|
<b:import resource="classpath:org/springframework/security/config/websocket/controllers.xml"/>
|
||||||
|
|
||||||
|
<websocket:message-broker path-matcher="pathMatcher">
|
||||||
|
<websocket:transport/>
|
||||||
|
<websocket:stomp-endpoint path="/app">
|
||||||
|
<websocket:handshake-handler ref="testHandler"/>
|
||||||
|
</websocket:stomp-endpoint>
|
||||||
|
|
||||||
|
<websocket:simple-broker prefix="/queue, /topic"/>
|
||||||
|
</websocket:message-broker>
|
||||||
|
|
||||||
|
<b:bean name="pathMatcher" class="org.springframework.util.AntPathMatcher">
|
||||||
|
<b:constructor-arg value="."/>
|
||||||
|
</b:bean>
|
||||||
|
|
||||||
|
<b:bean name="testHandler" class="org.springframework.security.config.websocket.WebSocketMessageBrokerConfigTests.TestHandshakeHandler"/>
|
||||||
|
|
||||||
|
<websocket-message-broker>
|
||||||
|
<intercept-message pattern="/denyAll.*" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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="DISCONNECT_ACK" access="permitAll"/>
|
||||||
|
<intercept-message pattern="/**" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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="HEARTBEAT" access="permitAll"/>
|
||||||
|
<intercept-message pattern="/**" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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="HEARTBEAT" access="permitAll"/>
|
||||||
|
<intercept-message pattern="/**" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,30 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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 id="inCsi">
|
||||||
|
<intercept-message pattern="/**" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,42 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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:websocket="http://www.springframework.org/schema/websocket"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.springframework.org/schema/security"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
|
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
|
||||||
|
|
||||||
|
<websocket:message-broker>
|
||||||
|
<websocket:transport/>
|
||||||
|
<websocket:stomp-endpoint path="/app">
|
||||||
|
<websocket:sockjs/>
|
||||||
|
</websocket:stomp-endpoint>
|
||||||
|
<websocket:simple-broker prefix="/queue, /topic"/>
|
||||||
|
<websocket:client-inbound-channel>
|
||||||
|
<websocket:interceptors>
|
||||||
|
<b:ref bean="inCsi"/>
|
||||||
|
</websocket:interceptors>
|
||||||
|
</websocket:client-inbound-channel>
|
||||||
|
</websocket:message-broker>
|
||||||
|
|
||||||
|
<websocket-message-broker id="inCsi">
|
||||||
|
<intercept-message pattern="/**" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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="MESSAGE" access="permitAll"/>
|
||||||
|
<intercept-message pattern="/**" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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" access="permitAll"/>
|
||||||
|
<intercept-message pattern="/denyAll" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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="OTHER" access="permitAll"/>
|
||||||
|
<intercept-message pattern="/**" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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:beans>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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/sync.xml"/>
|
||||||
|
<b:import resource="classpath:org/springframework/security/config/websocket/websocket.xml"/>
|
||||||
|
|
||||||
|
<websocket-message-broker>
|
||||||
|
<intercept-message pattern="/**" access="permitAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,50 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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:websocket="http://www.springframework.org/schema/websocket"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.springframework.org/schema/security"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
|
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
|
||||||
|
|
||||||
|
<b:import resource="classpath:org/springframework/security/config/websocket/controllers.xml"/>
|
||||||
|
<b:import resource="classpath:org/springframework/security/config/websocket/sync.xml"/>
|
||||||
|
|
||||||
|
<websocket:message-broker>
|
||||||
|
<websocket:transport/>
|
||||||
|
<websocket:stomp-endpoint path="/app">
|
||||||
|
<websocket:handshake-handler ref="testHandler"/>
|
||||||
|
<websocket:handshake-interceptors>
|
||||||
|
<b:bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor"/>
|
||||||
|
</websocket:handshake-interceptors>
|
||||||
|
</websocket:stomp-endpoint>
|
||||||
|
|
||||||
|
<websocket:simple-broker prefix="/queue, /topic"/>
|
||||||
|
<websocket:argument-resolvers>
|
||||||
|
<b:ref bean="messageArgumentResolver"/>
|
||||||
|
</websocket:argument-resolvers>
|
||||||
|
</websocket:message-broker>
|
||||||
|
|
||||||
|
<b:bean name="testHandler" class="org.springframework.security.config.websocket.WebSocketMessageBrokerConfigTests.TestHandshakeHandler"/>
|
||||||
|
<b:bean name="messageArgumentResolver" class="org.springframework.security.config.websocket.WebSocketMessageBrokerConfigTests.MessageArgumentResolver"/>
|
||||||
|
|
||||||
|
<websocket-message-broker>
|
||||||
|
<intercept-message pattern="/**" access="permitAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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/sync.xml"/>
|
||||||
|
<b:import resource="classpath:org/springframework/security/config/websocket/websocket.xml"/>
|
||||||
|
|
||||||
|
<websocket-message-broker same-origin-disabled="true">
|
||||||
|
<intercept-message pattern="/**" access="permitAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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/sync.xml"/>
|
||||||
|
<b:import resource="classpath:org/springframework/security/config/websocket/websocket-sockjs.xml"/>
|
||||||
|
|
||||||
|
<websocket-message-broker>
|
||||||
|
<intercept-message pattern="/**" access="permitAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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 http://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://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="UNSUBSCRIBE" access="permitAll"/>
|
||||||
|
<intercept-message pattern="/**" access="denyAll"/>
|
||||||
|
</websocket-message-broker>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,24 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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.
|
||||||
|
-->
|
||||||
|
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<bean class="org.springframework.security.config.websocket.WebSocketMessageBrokerConfigTests.MessageController"/>
|
||||||
|
<bean class="org.springframework.security.config.websocket.WebSocketMessageBrokerConfigTests.MessageWithArgumentController"/>
|
||||||
|
|
||||||
|
</beans>
|
@ -0,0 +1,22 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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.
|
||||||
|
-->
|
||||||
|
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<bean class="org.springframework.security.config.websocket.WebSocketMessageBrokerConfigTests.InboundExecutorPostProcessor"/>
|
||||||
|
</beans>
|
@ -0,0 +1,37 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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/websocket"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
|
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
|
||||||
|
|
||||||
|
<message-broker>
|
||||||
|
<transport/>
|
||||||
|
<stomp-endpoint path="/app">
|
||||||
|
<handshake-handler ref="testHandler"/>
|
||||||
|
<handshake-interceptors>
|
||||||
|
<b:bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor"/>
|
||||||
|
</handshake-interceptors>
|
||||||
|
<sockjs/>
|
||||||
|
</stomp-endpoint>
|
||||||
|
|
||||||
|
<simple-broker prefix="/queue, /topic"/>
|
||||||
|
</message-broker>
|
||||||
|
|
||||||
|
<b:bean name="testHandler" class="org.springframework.security.config.websocket.WebSocketMessageBrokerConfigTests.TestHandshakeHandler"/>
|
||||||
|
</b:beans>
|
@ -0,0 +1,36 @@
|
|||||||
|
<?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
|
||||||
|
~
|
||||||
|
~ http://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/websocket"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
|
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
|
||||||
|
|
||||||
|
<message-broker>
|
||||||
|
<transport/>
|
||||||
|
<stomp-endpoint path="/app">
|
||||||
|
<handshake-handler ref="testHandler"/>
|
||||||
|
<handshake-interceptors>
|
||||||
|
<b:bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor"/>
|
||||||
|
</handshake-interceptors>
|
||||||
|
</stomp-endpoint>
|
||||||
|
|
||||||
|
<simple-broker prefix="/queue, /topic"/>
|
||||||
|
</message-broker>
|
||||||
|
|
||||||
|
<b:bean name="testHandler" class="org.springframework.security.config.websocket.WebSocketMessageBrokerConfigTests.TestHandshakeHandler"/>
|
||||||
|
</b:beans>
|
Loading…
x
Reference in New Issue
Block a user