I did not find a better solution, but it works just fine for me.
By sending a JMS message, I save Authentication as a header and, accordingly, getting a recreation of the Security Context. To save Authentication as a header, you must serialize it as Base64 :
class AuthenticationSerializer { static String serialize(Authentication authentication) { byte[] bytes = SerializationUtils.serialize(authentication); return DatatypeConverter.printBase64Binary(bytes); } static Authentication deserialize(String authentication) { byte[] decoded = DatatypeConverter.parseBase64Binary(authentication); Authentication auth = (Authentication) SerializationUtils.deserialize(decoded); return auth; } }
By sending the message header you just set, you can create a Decorator for the message template so that it happens automatically. In you decorator just call this method:
private void attachAuthenticationContext(Message message){ Authentication auth = SecurityContextHolder.getContext().getAuthentication(); String serialized = AuthenticationSerializer.serialize(auth); message.setStringProperty("authcontext", serialized); }
Getting more complicated, but it can also be done automatically. Instead of using @EnableJMS use the following configuration:
@Configuration class JmsBootstrapConfiguration { @Bean(name = JmsListenerConfigUtils.JMS_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public JmsListenerAnnotationBeanPostProcessor jmsListenerAnnotationProcessor() { return new JmsListenerPostProcessor(); } @Bean(name = JmsListenerConfigUtils.JMS_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME) public JmsListenerEndpointRegistry defaultJmsListenerEndpointRegistry() { return new JmsListenerEndpointRegistry(); } } class JmsListenerPostProcessor extends JmsListenerAnnotationBeanPostProcessor { @Override protected MethodJmsListenerEndpoint createMethodJmsListenerEndpoint() { return new ListenerEndpoint(); } } class ListenerEndpoint extends MethodJmsListenerEndpoint { @Override protected MessagingMessageListenerAdapter createMessageListenerInstance() { return new ListenerAdapter(); } } class ListenerAdapter extends MessagingMessageListenerAdapter { @Override public void onMessage(Message jmsMessage, Session session) throws JMSException { propagateSecurityContext(jmsMessage); super.onMessage(jmsMessage, session); } private void propagateSecurityContext(Message jmsMessage) throws JMSException { String authStr = jmsMessage.getStringProperty("authcontext"); Authentication auth = AuthenticationSerializer.deserialize(authStr); SecurityContextHolder.getContext().setAuthentication(auth); } }
source share