【发布时间】:2019-12-15 22:10:14
【问题描述】:
我正在运行带有 Websockets 的 JHipster 6.1.2 网关,并试图限制对消息传递主题的访问,以便用户只能订阅他们所属机构的主题。所以基本上我想从订阅路径中检查id。
我目前的解决方案是基于https://stackoverflow.com/a/44895369/4246074,看起来如下:
WebsocketSecurityConfiguration.java:
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
//...
//User can only subscribe to own institution topic
.simpSubscribeDestMatchers("/topic/institution.{id}")
.access("@institutionIdGuard.checkInstitutionId(#id)")
//...
}
InstitutionIdGuard.java:
@Component
public class InstitutionIdGuard {
public boolean checkInstitutionId(Long institutionId) {
//validation logic for institutionId would go here
return true;
}
问题:
显然,SpEL 表达式无法从路径访问{id},因为我收到以下日志的空指针错误:
2019-08-08 10:30:08.367 ERROR 31097 --- [ XNIO-1 I/O-1] o.s.w.s.m.StompSubProtocolHandler : Failed to send client message to application via MessageChannel in session j2a0jlos. Sending STOMP ERROR to client.
org.springframework.messaging.MessageDeliveryException: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is java.lang.IllegalArgumentException: Failed to evaluate expression '@institutionIdGuard.checkInstitutionId(#id)'
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:146)
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:122)
at org.springframework.web.socket.messaging.StompSubProtocolHandler.handleMessageFromClient(StompSubProtocolHandler.java:284)
at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.handleMessage(SubProtocolWebSocketHandler.java:324)
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75)
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56)
at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:58)
at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.delegateMessages(AbstractSockJsSession.java:386)
at org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession.handleMessage(WebSocketServerSockJsSession.java:195)
at org.springframework.web.socket.sockjs.transport.handler.SockJsWebSocketHandler.handleTextMessage(SockJsWebSocketHandler.java:93)
at org.springframework.web.socket.handler.AbstractWebSocketHandler.handleMessage(AbstractWebSocketHandler.java:43)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:113)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$000(StandardWebSocketHandlerAdapter.java:42)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:84)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:81)
at io.undertow.websockets.jsr.FrameHandler$7.run(FrameHandler.java:286)
at io.undertow.websockets.jsr.ServerWebSocketContainer$1.call(ServerWebSocketContainer.java:170)
at io.undertow.websockets.jsr.ServerWebSocketContainer$1.call(ServerWebSocketContainer.java:167)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at io.undertow.websockets.jsr.ServerWebSocketContainer.invokeEndpointMethod(ServerWebSocketContainer.java:604)
at io.undertow.websockets.jsr.ServerWebSocketContainer.invokeEndpointMethod(ServerWebSocketContainer.java:594)
at io.undertow.websockets.jsr.FrameHandler.invokeTextHandler(FrameHandler.java:266)
at io.undertow.websockets.jsr.FrameHandler.onFullTextMessage(FrameHandler.java:317)
at io.undertow.websockets.core.AbstractReceiveListener$2.complete(AbstractReceiveListener.java:156)
at io.undertow.websockets.core.AbstractReceiveListener$2.complete(AbstractReceiveListener.java:152)
at io.undertow.websockets.core.BufferedTextMessage.read(BufferedTextMessage.java:105)
at io.undertow.websockets.core.AbstractReceiveListener.readBufferedText(AbstractReceiveListener.java:152)
at io.undertow.websockets.core.AbstractReceiveListener.bufferFullMessage(AbstractReceiveListener.java:90)
at io.undertow.websockets.jsr.FrameHandler.onText(FrameHandler.java:182)
at io.undertow.websockets.core.AbstractReceiveListener.handleEvent(AbstractReceiveListener.java:44)
at io.undertow.websockets.core.AbstractReceiveListener.handleEvent(AbstractReceiveListener.java:33)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at io.undertow.server.protocol.framed.AbstractFramedChannel$FrameReadListener.handleEvent(AbstractFramedChannel.java:951)
at io.undertow.server.protocol.framed.AbstractFramedChannel$FrameReadListener.handleEvent(AbstractFramedChannel.java:932)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
at org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:88)
at org.xnio.nio.WorkerThread.run(WorkerThread.java:561)
Caused by: java.lang.IllegalArgumentException: Failed to evaluate expression '@institutionIdGuard.checkInstitutionId(#id)'
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:30)
at org.springframework.security.messaging.access.expression.MessageExpressionVoter.vote(MessageExpressionVoter.java:57)
at org.springframework.security.messaging.access.expression.MessageExpressionVoter.vote(MessageExpressionVoter.java:39)
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:63)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233)
at org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor.preSend(ChannelSecurityInterceptor.java:69)
at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:178)
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:132)
... 37 common frames omitted
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1004E: Method call: Method checkInstitutionId(null) cannot be found on type com.mycompany.websocketgateway.security.InstitutionIdGuard
at org.springframework.expression.spel.ast.MethodReference.findAccessorForMethod(MethodReference.java:225)
at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:134)
at org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:54)
at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:390)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:90)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:114)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:300)
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:26)
... 44 common frames omitted
如果您有任何想法如何使我的解决方案发挥作用,或在id 中执行检查的其他其他方式,我将不胜感激。
【问题讨论】:
标签: spring-boot spring-security websocket jhipster spring-el