diff --git a/application/pom.xml b/application/pom.xml
index 91fe9f71f2..91965dfed5 100644
--- a/application/pom.xml
+++ b/application/pom.xml
@@ -126,7 +126,7 @@
org.springframework.boot
- spring-boot-starter-webflux
+ spring-boot-starter-websocket
io.jsonwebtoken
diff --git a/application/src/main/java/org/thingsboard/server/config/ThingsboardWebFluxSecurityConfig.java b/application/src/main/java/org/thingsboard/server/config/ThingsboardWebFluxSecurityConfig.java
deleted file mode 100644
index db8f599350..0000000000
--- a/application/src/main/java/org/thingsboard/server/config/ThingsboardWebFluxSecurityConfig.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Copyright © 2016-2019 The Thingsboard 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.thingsboard.server.config;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.authentication.ReactiveAuthenticationManager;
-import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
-import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
-import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
-import org.springframework.security.config.web.server.ServerHttpSecurity;
-import org.springframework.security.web.server.SecurityWebFilterChain;
-import org.springframework.security.web.server.context.ServerSecurityContextRepository;
-
-//@EnableWebFluxSecurity
-//@EnableReactiveMethodSecurity
-public class ThingsboardWebFluxSecurityConfig {
-
- private static final String WS_TOKEN_BASED_AUTH_ENTRY_POINT = "/api/ws/**";
-
- @Autowired
- private ReactiveAuthenticationManager webfluxAuthenticationManager;
-
- @Autowired
- private ServerSecurityContextRepository jwtTokenSecurityContextRepository;
-
- @Bean
- public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
- return http
- .cors()
- .and()
- .csrf().disable()
- .formLogin().disable()
- .httpBasic().disable()
- .exceptionHandling()
- .and()
- .authenticationManager(webfluxAuthenticationManager)
- .securityContextRepository(jwtTokenSecurityContextRepository)
- .authorizeExchange()
- .pathMatchers(WS_TOKEN_BASED_AUTH_ENTRY_POINT)
- .authenticated()
- .and()
- .build();
- }
-
-}
diff --git a/application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java b/application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java
index 6c08b1b9a6..b8b703e4fc 100644
--- a/application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java
+++ b/application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java
@@ -21,63 +21,44 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
-import org.springframework.web.reactive.HandlerMapping;
-import org.springframework.web.reactive.HandlerResult;
-import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
-import org.springframework.web.reactive.socket.WebSocketHandler;
-import org.springframework.web.reactive.socket.server.support.HandshakeWebSocketService;
-import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter;
-import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.socket.WebSocketHandler;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
+import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
+import org.springframework.web.socket.server.HandshakeInterceptor;
+import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
+import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.controller.plugin.TbWebSocketHandler;
import org.thingsboard.server.service.security.model.SecurityUser;
-import reactor.core.publisher.Mono;
-import java.util.HashMap;
import java.util.Map;
@Configuration
-public class WebSocketConfiguration {
+@EnableWebSocket
+public class WebSocketConfiguration implements WebSocketConfigurer {
public static final String WS_PLUGIN_PREFIX = "/api/ws/plugins/";
private static final String WS_PLUGIN_MAPPING = WS_PLUGIN_PREFIX + "**";
-/* @Bean
+ @Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(32768);
container.setMaxBinaryMessageBufferSize(32768);
return container;
- }*/
-
- @Bean
- public HandlerMapping handlerMapping() {
- Map map = new HashMap<>();
- map.put(WS_PLUGIN_MAPPING, wsHandler());
-
- SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
- mapping.setUrlMap(map);
- mapping.setOrder(-1); // before annotated controllers
- return mapping;
}
- @Bean
- public WebSocketHandlerAdapter handlerAdapter() {
- return new WebSocketHandlerAdapter();
- }
-
-/* @Override
+ @Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(wsHandler(), WS_PLUGIN_MAPPING).setAllowedOrigins("*")
.addInterceptors(new HttpSessionHandshakeInterceptor(), new HandshakeInterceptor() {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
- Map attributes) throws Exception {
+ Map attributes) throws Exception {
SecurityUser user = null;
try {
user = getCurrentUser();
@@ -92,23 +73,23 @@ public class WebSocketConfiguration {
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
- Exception exception) {
+ Exception exception) {
//Do nothing
}
});
- }*/
+ }
@Bean
public WebSocketHandler wsHandler() {
return new TbWebSocketHandler();
}
-/* protected SecurityUser getCurrentUser() throws ThingsboardException {
+ protected SecurityUser getCurrentUser() throws ThingsboardException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.getPrincipal() instanceof SecurityUser) {
return (SecurityUser) authentication.getPrincipal();
} else {
throw new ThingsboardException("You aren't authorized to perform this operation!", ThingsboardErrorCode.AUTHENTICATION);
}
- }*/
+ }
}
diff --git a/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java b/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java
index d20e4db433..169bba8895 100644
--- a/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java
+++ b/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java
@@ -16,51 +16,48 @@
package org.thingsboard.server.controller.plugin;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.BeanCreationNotAllowedException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
-import org.springframework.web.reactive.socket.CloseStatus;
-import org.springframework.web.reactive.socket.WebSocketHandler;
-import org.springframework.web.reactive.socket.WebSocketSession;
+import org.springframework.util.StringUtils;
+import org.springframework.web.socket.CloseStatus;
+import org.springframework.web.socket.TextMessage;
+import org.springframework.web.socket.WebSocketSession;
+import org.springframework.web.socket.adapter.NativeWebSocketSession;
+import org.springframework.web.socket.handler.TextWebSocketHandler;
+import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
+import org.thingsboard.server.common.data.id.CustomerId;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.id.UserId;
+import org.thingsboard.server.common.msg.tools.TbRateLimits;
+import org.thingsboard.server.config.WebSocketConfiguration;
import org.thingsboard.server.service.security.model.SecurityUser;
+import org.thingsboard.server.service.security.model.UserPrincipal;
+import org.thingsboard.server.service.telemetry.SessionEvent;
import org.thingsboard.server.service.telemetry.TelemetryWebSocketMsgEndpoint;
+import org.thingsboard.server.service.telemetry.TelemetryWebSocketService;
import org.thingsboard.server.service.telemetry.TelemetryWebSocketSessionRef;
-import reactor.core.publisher.Mono;
+import javax.websocket.*;
import java.io.IOException;
-import java.security.Principal;
+import java.net.URI;
+import java.security.InvalidParameterException;
+import java.util.Queue;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.LinkedBlockingQueue;
@Service
@Slf4j
-public class TbWebSocketHandler implements WebSocketHandler, TelemetryWebSocketMsgEndpoint {
+public class TbWebSocketHandler extends TextWebSocketHandler implements TelemetryWebSocketMsgEndpoint {
- @Override
- public Mono handle(WebSocketSession session) {
- return session.receive()
- .doOnNext(message -> {
- Principal principal = session.getHandshakeInfo().getPrincipal().block();
- if (principal instanceof SecurityUser) {
- SecurityUser currentUser = (SecurityUser) principal;
- log.info("[{}][{}] Processing {}", currentUser.getTenantId(), session.getId(), message.getPayloadAsText());
- } else {
- log.info("[{}] Principal {}", session.getId(), principal);
- log.info("[{}] Processing {}", session.getId(), message.getPayloadAsText());
- }
- })
- .then();
- }
-
- @Override
- public void send(TelemetryWebSocketSessionRef sessionRef, int subscriptionId, String msg) throws IOException {
+ private static final ConcurrentMap internalSessionMap = new ConcurrentHashMap<>();
+ private static final ConcurrentMap externalSessionMap = new ConcurrentHashMap<>();
- }
-
- @Override
- public void close(TelemetryWebSocketSessionRef sessionRef, CloseStatus withReason) throws IOException {
-
- }
-
-// private static final ConcurrentMap internalSessionMap = new ConcurrentHashMap<>();
-// private static final ConcurrentMap externalSessionMap = new ConcurrentHashMap<>();
-/*
@Autowired
private TelemetryWebSocketService webSocketService;
@@ -105,22 +102,6 @@ public class TbWebSocketHandler implements WebSocketHandler, TelemetryWebSocketM
}
}
- @Override
- public Mono handle(WebSocketSession session) {
- return session.receive()
- .doOnNext(message -> {
- Principal principal = session.getHandshakeInfo().getPrincipal().block();
- if (principal instanceof SecurityUser) {
- SecurityUser currentUser = (SecurityUser) principal;
- log.info("[{}][{}] Processing {}", currentUser.getTenantId(), session.getId(), message.getPayloadAsText());
- } else {
- log.info("[{}] Principal {}", session.getId(), principal);
- log.info("[{}] Processing {}", session.getId(), message.getPayloadAsText());
- }
- })
- .then();
- }
-
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
super.afterConnectionEstablished(session);
@@ -410,5 +391,5 @@ public class TbWebSocketHandler implements WebSocketHandler, TelemetryWebSocketM
}
}
}
- */
-}
+
+}
\ No newline at end of file
diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/webflux/WebfluxAuthenticationManager.java b/application/src/main/java/org/thingsboard/server/service/security/auth/webflux/WebfluxAuthenticationManager.java
deleted file mode 100644
index 35bee6e9bd..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/security/auth/webflux/WebfluxAuthenticationManager.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * Copyright © 2016-2019 The Thingsboard 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.thingsboard.server.service.security.auth.webflux;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.authentication.ReactiveAuthenticationManager;
-import org.springframework.security.core.Authentication;
-import org.springframework.stereotype.Component;
-import org.thingsboard.server.service.security.auth.JwtAuthenticationToken;
-import org.thingsboard.server.service.security.model.SecurityUser;
-import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
-import org.thingsboard.server.service.security.model.token.RawAccessJwtToken;
-import reactor.core.publisher.Mono;
-
-@Component
-public class WebfluxAuthenticationManager implements ReactiveAuthenticationManager {
-
- @Autowired
- private JwtTokenFactory tokenFactory;
-
- @Override
- public Mono authenticate(Authentication authentication) {
- try {
- if (authentication.getCredentials() != null && authentication.getCredentials() instanceof RawAccessJwtToken) {
- RawAccessJwtToken rawAccessToken = (RawAccessJwtToken) authentication.getCredentials();
- SecurityUser securityUser = tokenFactory.parseAccessJwtToken(rawAccessToken);
- JwtAuthenticationToken auth = new JwtAuthenticationToken(securityUser);
- return Mono.just(auth);
- }
- return Mono.empty();
- } catch (Exception e) {
- return Mono.error(e);
- }
- }
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/webflux/jwt/JwtTokenSecurityContextRepository.java b/application/src/main/java/org/thingsboard/server/service/security/auth/webflux/jwt/JwtTokenSecurityContextRepository.java
deleted file mode 100644
index f6fe103fc5..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/security/auth/webflux/jwt/JwtTokenSecurityContextRepository.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Copyright © 2016-2019 The Thingsboard 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.thingsboard.server.service.security.auth.webflux.jwt;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.authentication.ReactiveAuthenticationManager;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextImpl;
-import org.springframework.security.web.server.context.ServerSecurityContextRepository;
-import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
-import org.springframework.stereotype.Component;
-import org.springframework.util.StringUtils;
-import org.springframework.web.server.ServerWebExchange;
-import org.thingsboard.server.config.ThingsboardSecurityConfiguration;
-import org.thingsboard.server.service.security.auth.JwtAuthenticationToken;
-import org.thingsboard.server.service.security.auth.jwt.extractor.TokenExtractor;
-import org.thingsboard.server.service.security.model.token.RawAccessJwtToken;
-import reactor.core.publisher.Mono;
-
-import java.util.List;
-
-@Component
-public class JwtTokenSecurityContextRepository implements ServerSecurityContextRepository {
-
- public static final String DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME = "SPRING_SECURITY_CONTEXT";
-
- @Autowired
- private ReactiveAuthenticationManager webfluxAuthenticationManager;
-
- @Override
- public Mono save(ServerWebExchange exchange, SecurityContext context) {
- return exchange.getSession()
- .doOnNext(session -> {
- if (context == null) {
- session.getAttributes().remove(WebSessionServerSecurityContextRepository.DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME);
- } else {
- session.getAttributes().put(WebSessionServerSecurityContextRepository.DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME, context);
- }
- })
- .flatMap(session -> session.changeSessionId());
- }
-
- @Override
- public Mono load(ServerWebExchange exchange) {
- ServerHttpRequest request = exchange.getRequest();
- String token = extractTokenFromQuery(request);
- if (!StringUtils.isEmpty(token)) {
- RawAccessJwtToken rawToken = new RawAccessJwtToken(token);
- Authentication auth = new JwtAuthenticationToken(rawToken);
- return this.webfluxAuthenticationManager.authenticate(auth).map((authentication) -> {
- return new SecurityContextImpl(authentication);
- });
- } else {
- return Mono.empty();
- }
- }
-
- private String extractTokenFromQuery(ServerHttpRequest request) {
- String token = null;
- if (request.getQueryParams() != null) {
- List tokenParamValue = request.getQueryParams().get(ThingsboardSecurityConfiguration.JWT_TOKEN_QUERY_PARAM);
- if (tokenParamValue != null && !tokenParamValue.isEmpty()) {
- token = tokenParamValue.get(0);
- }
- }
- return token;
- }
-
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetryWebSocketService.java b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetryWebSocketService.java
index 68646153a6..86747150c9 100644
--- a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetryWebSocketService.java
+++ b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetryWebSocketService.java
@@ -26,7 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
-import org.springframework.web.reactive.socket.CloseStatus;
+import org.springframework.web.socket.CloseStatus;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EntityId;
diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/TelemetryWebSocketMsgEndpoint.java b/application/src/main/java/org/thingsboard/server/service/telemetry/TelemetryWebSocketMsgEndpoint.java
index ca3a91600f..8c18f2d42b 100644
--- a/application/src/main/java/org/thingsboard/server/service/telemetry/TelemetryWebSocketMsgEndpoint.java
+++ b/application/src/main/java/org/thingsboard/server/service/telemetry/TelemetryWebSocketMsgEndpoint.java
@@ -15,7 +15,7 @@
*/
package org.thingsboard.server.service.telemetry;
-import org.springframework.web.reactive.socket.CloseStatus;
+import org.springframework.web.socket.CloseStatus;
import java.io.IOException;
diff --git a/pom.xml b/pom.xml
index eb0650a124..d3ff7a1635 100755
--- a/pom.xml
+++ b/pom.xml
@@ -50,7 +50,7 @@
1.5.0
2.5
1.4
- 2.9.0
+ 2.9.7
2.2.6
2.11
2.4.2
@@ -424,7 +424,7 @@
org.springframework.boot
- spring-boot-starter-webflux
+ spring-boot-starter-websocket
${spring-boot.version}