gpt4 book ai didi

java - 使用 Spring Security 和 Rabbitmq 的 OAuth2 授权

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:32:52 24 4
gpt4 key购买 nike

我们目前有许多与 REST 端点和 RabbitMQ 队列通信的 Spring 微服务。我们刚刚在所有服务上实现了 OAuth2 安全性,并且 REST 端点得到了适当的保护。

我们有一个我们编写的库,它创建了 RabbitTemplate 和 AmqpAdmin bean,这样样板代码就不必在每个服务中完成。我们在 Spring 中使用特定用户连接到 RabbitMQ 服务器,普通客户端使用特定用户,管理员使用另一个用户。我们不想以个人用户身份连接到 RabbitMQ 服务器。

如果我们在 rabbit 消息头中传递访问 token ,是否可以配置 RabbitTemplate 在处理消息之前检查 token ?这是否可以/应该在模板的全局 AfterReceive/BeforePublish 处理器中完成?或者这是否需要在每个监听器方法中单独检查?

谢谢

最佳答案

我能够通过创建自定义 MessageListenerContainerFactory 和 MessageListenerContainer 来制定解决方案。

CustomMessageListenerContainerFactory.java:


public class CustomMessageListenerContainerFactory extends AbstractRabbitListenerContainerFactory {

DefaultTokenServices tokenServices;

public CustomMessageListenerContainerFactory(DefaultTokenServices tokenServices) {
this.tokenServices = tokenServices;
}

/**
* Create an empty container instance.
*
* @return the new container instance.
*/
@Override
protected CustomMessageListenerContainer createContainerInstance() {
return new CustomMessageListenerContainer(tokenServices);
}
}

CustomMessageListenerContainer.java:


public class CustomMessageListenerContainer extends SimpleMessageListenerContainer {
private final static String errorMessage = "No valid credentials found in request: {}";
private final static String handlingMessage = "Handling queue: {}";
private final static String receivedMessage = "Received Message: {}";
private final static Logger logger = LoggerFactory.getLogger(CustomMessageListenerContainer.class);


private DefaultTokenServices tokenServices;

/**
* Constructor
*
* @param tokenServices The instance of DefaultTokenServices used to decrypt the access token.
*/
public CustomMessageListenerContainer(DefaultTokenServices tokenServices) {
this.tokenServices = tokenServices;
}

/**
* This method checks to see if there is a valid authorization
*
* @param channel The AMQP channel on which the message was published.
* @param messageIn The incoming message.
* @throws Exception Throws an exception when there are no valid credentials in the message.
*/
@Override
protected void executeListener(Channel channel, Message messageIn) throws Exception {
logger.info(handlingMessage, (Object[]) getQueueNames());
logger.info(receivedMessage, BeanUtils.beanProperties(messageIn));
if (messageIn.getMessageProperties().getHeaders().keySet().stream().anyMatch(t -> Objects.equals(t.toLowerCase(), "authorization"))) {
String accessKey = messageIn.getMessageProperties()
.getHeaders()
.keySet()
.stream()
.filter(t -> Objects.equals(t.toLowerCase(), "authorization"))
.findFirst()
.get();
OAuth2Authentication auth = tokenServices.loadAuthentication(messageIn.getMessageProperties().getHeaders().get(accessKey).toString());
// If the token is expired, there will be no auth.
if (auth != null) {
SecurityContextHolder.getContext().setAuthentication(auth);
super.executeListener(channel, messageIn);
return;
}
}
rejectMessage(channel, messageIn);
}

private void rejectMessage(Channel channel, Message messageIn) throws Exception {
logger.info(errorMessage, (Object[]) getQueueNames());
String localMessage = errorMessage.replace("{}", String.join(", ", getQueueNames()));
if (messageIn.getMessageProperties().getReplyTo() != null) {
channel.basicPublish("",
messageIn.getMessageProperties().getReplyTo(),
new AMQP.BasicProperties.Builder()
.contentType("application/json")
.correlationId(messageIn.getMessageProperties().getCorrelationId())
.build(),
"{\"errorMessage\":\"".concat(localMessage).concat("\"}").getBytes());
}
throw new AmqpRejectAndDontRequeueException(localMessage);
}
}

CustomRabbitListenerConfigurer.java:

...
@Override
public void configureRabbitListeners(final RabbitListenerEndpointRegistrar registrar) {
registrar.setMessageHandlerMethodFactory(messageHandlerMethodFactory());
CustomMessageListenerContainerfactory factory = new CustomMessageListenerContainerfactory(tokenServices);
ConnectionFactory connectionFactory = context.getBean(ConnectionFactory.class);
factory.setConnectionFactory(connectionFactory);
registrar.setContainerFactory(factory);
}
...

关于java - 使用 Spring Security 和 Rabbitmq 的 OAuth2 授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50358936/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com