Fixed issue #440, moved read access check on connect instead of on publish
This commit is contained in:
@@ -260,7 +260,7 @@ final class MQTTConnection {
|
||||
}
|
||||
connected = false;
|
||||
//dispatch connection lost to intercept.
|
||||
String userName= NettyUtils.userName(channel);
|
||||
String userName = NettyUtils.userName(channel);
|
||||
postOffice.dispatchConnectionLost(clientID,userName);
|
||||
LOG.trace("dispatch disconnection: clientId={}, userName={}", clientID, userName);
|
||||
}
|
||||
@@ -290,7 +290,7 @@ final class MQTTConnection {
|
||||
connected = false;
|
||||
channel.close().addListener(FIRE_EXCEPTION_ON_FAILURE);
|
||||
LOG.trace("Processed DISCONNECT CId={}, channel: {}", clientID, channel);
|
||||
String userName=NettyUtils.userName(channel);
|
||||
String userName = NettyUtils.userName(channel);
|
||||
postOffice.dispatchDisconnection(clientID,userName);
|
||||
LOG.trace("dispatch disconnection: clientId={}, userName={}", clientID, userName);
|
||||
}
|
||||
@@ -432,6 +432,10 @@ final class MQTTConnection {
|
||||
return NettyUtils.clientID(channel);
|
||||
}
|
||||
|
||||
String getUsername() {
|
||||
return NettyUtils.userName(channel);
|
||||
}
|
||||
|
||||
public void sendPublishRetainedQos0(Topic topic, MqttQoS qos, ByteBuf payload) {
|
||||
MqttPublishMessage publishMsg = retainedPublish(topic.toString(), qos, payload);
|
||||
sendPublish(publishMsg);
|
||||
|
||||
@@ -19,7 +19,6 @@ import io.moquette.interception.BrokerInterceptor;
|
||||
import io.moquette.broker.subscriptions.ISubscriptionsDirectory;
|
||||
import io.moquette.broker.subscriptions.Subscription;
|
||||
import io.moquette.broker.subscriptions.Topic;
|
||||
import io.moquette.broker.security.IAuthorizatorPolicy;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.handler.codec.mqtt.*;
|
||||
@@ -45,9 +44,9 @@ class PostOffice {
|
||||
private SessionRegistry sessionRegistry;
|
||||
private BrokerInterceptor interceptor;
|
||||
|
||||
PostOffice(ISubscriptionsDirectory subscriptions, IAuthorizatorPolicy authorizatorPolicy,
|
||||
IRetainedRepository retainedRepository, SessionRegistry sessionRegistry, BrokerInterceptor interceptor) {
|
||||
this.authorizator = new Authorizator(authorizatorPolicy);
|
||||
PostOffice(ISubscriptionsDirectory subscriptions, IRetainedRepository retainedRepository,
|
||||
SessionRegistry sessionRegistry, BrokerInterceptor interceptor, Authorizator authorizator) {
|
||||
this.authorizator = authorizator;
|
||||
this.subscriptions = subscriptions;
|
||||
this.retainedRepository = retainedRepository;
|
||||
this.sessionRegistry = sessionRegistry;
|
||||
@@ -217,11 +216,11 @@ class PostOffice {
|
||||
if (isSessionPresent) {
|
||||
LOG.debug("Sending PUBLISH message to active subscriber CId: {}, topicFilter: {}, qos: {}",
|
||||
sub.getClientId(), sub.getTopicFilter(), qos);
|
||||
//TODO determine the user bounded to targetSession
|
||||
if (!authorizator.canRead(topic, "TODO", sub.getClientId())) {
|
||||
LOG.debug("Authorizator prohibit Client {} to be notified on {}", sub.getClientId(), topic);
|
||||
return;
|
||||
}
|
||||
// final String login = targetSession.login();
|
||||
// if (!authorizator.canRead(topic, login, sub.getClientId())) {
|
||||
// LOG.debug("Authorizator prohibit Client {} to be notified on {}", sub.getClientId(), topic);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// we need to retain because duplicate only copy r/w indexes and don't retain() causing refCnt = 0
|
||||
ByteBuf payload = origPayload.retainedDuplicate();
|
||||
|
||||
@@ -178,8 +178,9 @@ public class Server {
|
||||
|
||||
ISubscriptionsDirectory subscriptions = new CTrieSubscriptionDirectory();
|
||||
subscriptions.init(subscriptionsRepository);
|
||||
SessionRegistry sessions = new SessionRegistry(subscriptions, queueRepository);
|
||||
dispatcher = new PostOffice(subscriptions, authorizatorPolicy, retainedRepository, sessions, interceptor);
|
||||
final Authorizator authorizator = new Authorizator(authorizatorPolicy);
|
||||
SessionRegistry sessions = new SessionRegistry(subscriptions, queueRepository, authorizator);
|
||||
dispatcher = new PostOffice(subscriptions, retainedRepository, sessions, interceptor, authorizator);
|
||||
final BrokerConfiguration brokerConfig = new BrokerConfiguration(config);
|
||||
MQTTConnectionFactory connectionFactory = new MQTTConnectionFactory(brokerConfig, authenticator, sessions,
|
||||
dispatcher);
|
||||
|
||||
@@ -362,6 +362,14 @@ class Session {
|
||||
ReferenceCountUtil.release(removedMsg);
|
||||
}
|
||||
|
||||
// public String login() {
|
||||
// if (!connected()) {
|
||||
// throw new IllegalStateException("Can't ask login on disconnected session");
|
||||
// }
|
||||
//
|
||||
// return NettyUtils.userName(mqttConnection.channel);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Session{" +
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class SessionRegistry {
|
||||
@@ -61,11 +60,15 @@ public class SessionRegistry {
|
||||
private final ConcurrentMap<String, Session> pool = new ConcurrentHashMap<>();
|
||||
private final ISubscriptionsDirectory subscriptionsDirectory;
|
||||
private final IQueueRepository queueRepository;
|
||||
private final Authorizator authorizator;
|
||||
private final ConcurrentMap<String, Queue<SessionRegistry.EnqueuedMessage>> queues = new ConcurrentHashMap<>();
|
||||
|
||||
SessionRegistry(ISubscriptionsDirectory subscriptionsDirectory, IQueueRepository queueRepository) {
|
||||
SessionRegistry(ISubscriptionsDirectory subscriptionsDirectory,
|
||||
IQueueRepository queueRepository,
|
||||
Authorizator authorizator) {
|
||||
this.subscriptionsDirectory = subscriptionsDirectory;
|
||||
this.queueRepository = queueRepository;
|
||||
this.authorizator = authorizator;
|
||||
}
|
||||
|
||||
void bindToSession(MQTTConnection mqttConnection, MqttConnectMessage msg, String clientId) {
|
||||
@@ -129,7 +132,8 @@ public class SessionRegistry {
|
||||
LOG.trace("case 2, oldSession with same CId {} disconnected", clientId);
|
||||
} else if (!newIsClean && oldSession.disconnected()) {
|
||||
// case 3
|
||||
reactivateSubscriptions(oldSession);
|
||||
final String username = mqttConnection.getUsername();
|
||||
reactivateSubscriptions(oldSession, username);
|
||||
|
||||
// mark as connected
|
||||
final boolean connecting = oldSession.assignState(SessionStatus.DISCONNECTED, SessionStatus.CONNECTING);
|
||||
@@ -165,8 +169,14 @@ public class SessionRegistry {
|
||||
return postConnectAction;
|
||||
}
|
||||
|
||||
private void reactivateSubscriptions(Session session) {
|
||||
private void reactivateSubscriptions(Session session, String username) {
|
||||
//verify if subscription still satisfy read ACL permissions
|
||||
for (Subscription existingSub : session.getSubscriptions()) {
|
||||
final boolean topicReadable = authorizator.canRead(existingSub.getTopicFilter(), username,
|
||||
session.getClientID());
|
||||
if (!topicReadable) {
|
||||
subscriptionsDirectory.removeSubscription(existingSub.getTopicFilter(), session.getClientID());
|
||||
}
|
||||
// TODO
|
||||
// subscriptionsDirectory.reactivate(existingSub.getTopicFilter(), session.getClientID());
|
||||
}
|
||||
|
||||
@@ -65,9 +65,11 @@ public class MQTTConnectionConnectTest {
|
||||
subscriptions.init(subscriptionsRepository);
|
||||
queueRepository = new MemoryQueueRepository();
|
||||
|
||||
sessionRegistry = new SessionRegistry(subscriptions, queueRepository);
|
||||
postOffice = new PostOffice(subscriptions, new PermitAllAuthorizatorPolicy(), new MemoryRetainedRepository(),
|
||||
sessionRegistry, ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
|
||||
final PermitAllAuthorizatorPolicy authorizatorPolicy = new PermitAllAuthorizatorPolicy();
|
||||
final Authorizator permitAll = new Authorizator(authorizatorPolicy);
|
||||
sessionRegistry = new SessionRegistry(subscriptions, queueRepository, permitAll);
|
||||
postOffice = new PostOffice(subscriptions, new MemoryRetainedRepository(), sessionRegistry,
|
||||
ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR, permitAll);
|
||||
|
||||
sut = createMQTTConnection(CONFIG);
|
||||
channel = (EmbeddedChannel) sut.channel;
|
||||
|
||||
@@ -70,10 +70,11 @@ public class MQTTConnectionPublishTest {
|
||||
subscriptions.init(subscriptionsRepository);
|
||||
queueRepository = new MemoryQueueRepository();
|
||||
|
||||
sessionRegistry = new SessionRegistry(subscriptions, queueRepository);
|
||||
final PostOffice postOffice = new PostOffice(subscriptions, new PermitAllAuthorizatorPolicy(),
|
||||
new MemoryRetainedRepository(), sessionRegistry,
|
||||
ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
|
||||
final PermitAllAuthorizatorPolicy authorizatorPolicy = new PermitAllAuthorizatorPolicy();
|
||||
final Authorizator permitAll = new Authorizator(authorizatorPolicy);
|
||||
sessionRegistry = new SessionRegistry(subscriptions, queueRepository, permitAll);
|
||||
final PostOffice postOffice = new PostOffice(subscriptions,
|
||||
new MemoryRetainedRepository(), sessionRegistry, ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR, permitAll);
|
||||
return new MQTTConnection(channel, config, mockAuthenticator, sessionRegistry, postOffice);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,9 +85,11 @@ public class PostOfficeInternalPublishTest {
|
||||
retainedRepository = new MemoryRetainedRepository();
|
||||
queueRepository = new MemoryQueueRepository();
|
||||
|
||||
SessionRegistry sessionRegistry = new SessionRegistry(subscriptions, queueRepository);
|
||||
sut = new PostOffice(subscriptions, new PermitAllAuthorizatorPolicy(), retainedRepository, sessionRegistry,
|
||||
ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
|
||||
final PermitAllAuthorizatorPolicy authorizatorPolicy = new PermitAllAuthorizatorPolicy();
|
||||
final Authorizator permitAll = new Authorizator(authorizatorPolicy);
|
||||
SessionRegistry sessionRegistry = new SessionRegistry(subscriptions, queueRepository, permitAll);
|
||||
sut = new PostOffice(subscriptions, retainedRepository, sessionRegistry,
|
||||
ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR, permitAll);
|
||||
return sessionRegistry;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,9 +92,11 @@ public class PostOfficePublishTest {
|
||||
retainedRepository = new MemoryRetainedRepository();
|
||||
queueRepository = new MemoryQueueRepository();
|
||||
|
||||
SessionRegistry sessionRegistry = new SessionRegistry(subscriptions, queueRepository);
|
||||
sut = new PostOffice(subscriptions, new PermitAllAuthorizatorPolicy(), retainedRepository, sessionRegistry,
|
||||
ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
|
||||
final PermitAllAuthorizatorPolicy authorizatorPolicy = new PermitAllAuthorizatorPolicy();
|
||||
final Authorizator permitAll = new Authorizator(authorizatorPolicy);
|
||||
SessionRegistry sessionRegistry = new SessionRegistry(subscriptions, queueRepository, permitAll);
|
||||
sut = new PostOffice(subscriptions, retainedRepository, sessionRegistry,
|
||||
ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR, permitAll);
|
||||
return sessionRegistry;
|
||||
}
|
||||
|
||||
|
||||
@@ -90,9 +90,11 @@ public class PostOfficeSubscribeTest {
|
||||
subscriptions.init(subscriptionsRepository);
|
||||
queueRepository = new MemoryQueueRepository();
|
||||
|
||||
sessionRegistry = new SessionRegistry(subscriptions, queueRepository);
|
||||
sut = new PostOffice(subscriptions, new PermitAllAuthorizatorPolicy(), new MemoryRetainedRepository(),
|
||||
sessionRegistry, ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
|
||||
final PermitAllAuthorizatorPolicy authorizatorPolicy = new PermitAllAuthorizatorPolicy();
|
||||
final Authorizator permitAll = new Authorizator(authorizatorPolicy);
|
||||
sessionRegistry = new SessionRegistry(subscriptions, queueRepository, permitAll);
|
||||
sut = new PostOffice(subscriptions, new MemoryRetainedRepository(), sessionRegistry,
|
||||
ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR, permitAll);
|
||||
}
|
||||
|
||||
private MQTTConnection createMQTTConnection(BrokerConfiguration config, Channel channel) {
|
||||
@@ -164,8 +166,8 @@ public class PostOfficeSubscribeTest {
|
||||
when(prohibitReadOnNewsTopic.canRead(eq(new Topic(NEWS_TOPIC)), eq(FAKE_USER_NAME), eq(FAKE_CLIENT_ID)))
|
||||
.thenReturn(false);
|
||||
|
||||
sut = new PostOffice(subscriptions, prohibitReadOnNewsTopic, new MemoryRetainedRepository(), sessionRegistry,
|
||||
ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
|
||||
sut = new PostOffice(subscriptions, new MemoryRetainedRepository(), sessionRegistry,
|
||||
ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR, new Authorizator(prohibitReadOnNewsTopic));
|
||||
|
||||
connection.processConnect(connectMessage);
|
||||
ConnectionTestUtils.assertConnectAccepted(channel);
|
||||
|
||||
@@ -81,9 +81,11 @@ public class PostOfficeUnsubscribeTest {
|
||||
subscriptions.init(subscriptionsRepository);
|
||||
queueRepository = new MemoryQueueRepository();
|
||||
|
||||
sessionRegistry = new SessionRegistry(subscriptions, queueRepository);
|
||||
sut = new PostOffice(subscriptions, new PermitAllAuthorizatorPolicy(), new MemoryRetainedRepository(),
|
||||
sessionRegistry, ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
|
||||
final PermitAllAuthorizatorPolicy authorizatorPolicy = new PermitAllAuthorizatorPolicy();
|
||||
final Authorizator permitAll = new Authorizator(authorizatorPolicy);
|
||||
sessionRegistry = new SessionRegistry(subscriptions, queueRepository, permitAll);
|
||||
sut = new PostOffice(subscriptions, new MemoryRetainedRepository(), sessionRegistry,
|
||||
ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR, permitAll);
|
||||
}
|
||||
|
||||
private MQTTConnection createMQTTConnection(BrokerConfiguration config, Channel channel) {
|
||||
|
||||
@@ -70,10 +70,11 @@ public class SessionRegistryTest {
|
||||
subscriptions.init(subscriptionsRepository);
|
||||
queueRepository = new MemoryQueueRepository();
|
||||
|
||||
sut = new SessionRegistry(subscriptions, queueRepository);
|
||||
final PostOffice postOffice = new PostOffice(subscriptions, new PermitAllAuthorizatorPolicy(),
|
||||
new MemoryRetainedRepository(), sut,
|
||||
ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
|
||||
final PermitAllAuthorizatorPolicy authorizatorPolicy = new PermitAllAuthorizatorPolicy();
|
||||
final Authorizator permitAll = new Authorizator(authorizatorPolicy);
|
||||
sut = new SessionRegistry(subscriptions, queueRepository, permitAll);
|
||||
final PostOffice postOffice = new PostOffice(subscriptions,
|
||||
new MemoryRetainedRepository(), sut, ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR, permitAll);
|
||||
return new MQTTConnection(channel, config, mockAuthenticator, sut, postOffice);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user