Commit 83d4dbc6e5426f30c1a74655460e052c11204350

Authored by Volodymyr Babak
1 parent 1022a3dc

Websockets reverted

... ... @@ -126,7 +126,7 @@
126 126 </dependency>
127 127 <dependency>
128 128 <groupId>org.springframework.boot</groupId>
129   - <artifactId>spring-boot-starter-webflux</artifactId>
  129 + <artifactId>spring-boot-starter-websocket</artifactId>
130 130 </dependency>
131 131 <dependency>
132 132 <groupId>io.jsonwebtoken</groupId>
... ...
1   -/**
2   - * Copyright © 2016-2019 The Thingsboard Authors
3   - *
4   - * Licensed under the Apache License, Version 2.0 (the "License");
5   - * you may not use this file except in compliance with the License.
6   - * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
10   - * Unless required by applicable law or agreed to in writing, software
11   - * distributed under the License is distributed on an "AS IS" BASIS,
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   - * See the License for the specific language governing permissions and
14   - * limitations under the License.
15   - */
16   -package org.thingsboard.server.config;
17   -
18   -import org.springframework.beans.factory.annotation.Autowired;
19   -import org.springframework.context.annotation.Bean;
20   -import org.springframework.security.authentication.AuthenticationManager;
21   -import org.springframework.security.authentication.ReactiveAuthenticationManager;
22   -import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
23   -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
24   -import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
25   -import org.springframework.security.config.web.server.ServerHttpSecurity;
26   -import org.springframework.security.web.server.SecurityWebFilterChain;
27   -import org.springframework.security.web.server.context.ServerSecurityContextRepository;
28   -
29   -//@EnableWebFluxSecurity
30   -//@EnableReactiveMethodSecurity
31   -public class ThingsboardWebFluxSecurityConfig {
32   -
33   - private static final String WS_TOKEN_BASED_AUTH_ENTRY_POINT = "/api/ws/**";
34   -
35   - @Autowired
36   - private ReactiveAuthenticationManager webfluxAuthenticationManager;
37   -
38   - @Autowired
39   - private ServerSecurityContextRepository jwtTokenSecurityContextRepository;
40   -
41   - @Bean
42   - public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
43   - return http
44   - .cors()
45   - .and()
46   - .csrf().disable()
47   - .formLogin().disable()
48   - .httpBasic().disable()
49   - .exceptionHandling()
50   - .and()
51   - .authenticationManager(webfluxAuthenticationManager)
52   - .securityContextRepository(jwtTokenSecurityContextRepository)
53   - .authorizeExchange()
54   - .pathMatchers(WS_TOKEN_BASED_AUTH_ENTRY_POINT)
55   - .authenticated()
56   - .and()
57   - .build();
58   - }
59   -
60   -}
... ... @@ -21,63 +21,44 @@ import org.springframework.http.HttpStatus;
21 21 import org.springframework.http.server.ServerHttpRequest;
22 22 import org.springframework.http.server.ServerHttpResponse;
23 23 import org.springframework.security.core.Authentication;
24   -import org.springframework.security.core.context.SecurityContext;
25 24 import org.springframework.security.core.context.SecurityContextHolder;
26   -import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
27   -import org.springframework.web.reactive.HandlerMapping;
28   -import org.springframework.web.reactive.HandlerResult;
29   -import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
30   -import org.springframework.web.reactive.socket.WebSocketHandler;
31   -import org.springframework.web.reactive.socket.server.support.HandshakeWebSocketService;
32   -import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter;
33   -import org.springframework.web.server.ServerWebExchange;
  25 +import org.springframework.web.socket.WebSocketHandler;
  26 +import org.springframework.web.socket.config.annotation.EnableWebSocket;
  27 +import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
  28 +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
  29 +import org.springframework.web.socket.server.HandshakeInterceptor;
  30 +import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
  31 +import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
34 32 import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
35 33 import org.thingsboard.server.common.data.exception.ThingsboardException;
36 34 import org.thingsboard.server.controller.plugin.TbWebSocketHandler;
37 35 import org.thingsboard.server.service.security.model.SecurityUser;
38   -import reactor.core.publisher.Mono;
39 36
40   -import java.util.HashMap;
41 37 import java.util.Map;
42 38
43 39 @Configuration
44   -public class WebSocketConfiguration {
  40 +@EnableWebSocket
  41 +public class WebSocketConfiguration implements WebSocketConfigurer {
45 42
46 43 public static final String WS_PLUGIN_PREFIX = "/api/ws/plugins/";
47 44 private static final String WS_PLUGIN_MAPPING = WS_PLUGIN_PREFIX + "**";
48 45
49   -/* @Bean
  46 + @Bean
50 47 public ServletServerContainerFactoryBean createWebSocketContainer() {
51 48 ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
52 49 container.setMaxTextMessageBufferSize(32768);
53 50 container.setMaxBinaryMessageBufferSize(32768);
54 51 return container;
55   - }*/
56   -
57   - @Bean
58   - public HandlerMapping handlerMapping() {
59   - Map<String, WebSocketHandler> map = new HashMap<>();
60   - map.put(WS_PLUGIN_MAPPING, wsHandler());
61   -
62   - SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
63   - mapping.setUrlMap(map);
64   - mapping.setOrder(-1); // before annotated controllers
65   - return mapping;
66 52 }
67 53
68   - @Bean
69   - public WebSocketHandlerAdapter handlerAdapter() {
70   - return new WebSocketHandlerAdapter();
71   - }
72   -
73   -/* @Override
  54 + @Override
74 55 public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
75 56 registry.addHandler(wsHandler(), WS_PLUGIN_MAPPING).setAllowedOrigins("*")
76 57 .addInterceptors(new HttpSessionHandshakeInterceptor(), new HandshakeInterceptor() {
77 58
78 59 @Override
79 60 public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
80   - Map<String, Object> attributes) throws Exception {
  61 + Map<String, Object> attributes) throws Exception {
81 62 SecurityUser user = null;
82 63 try {
83 64 user = getCurrentUser();
... ... @@ -92,23 +73,23 @@ public class WebSocketConfiguration {
92 73
93 74 @Override
94 75 public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
95   - Exception exception) {
  76 + Exception exception) {
96 77 //Do nothing
97 78 }
98 79 });
99   - }*/
  80 + }
100 81
101 82 @Bean
102 83 public WebSocketHandler wsHandler() {
103 84 return new TbWebSocketHandler();
104 85 }
105 86
106   -/* protected SecurityUser getCurrentUser() throws ThingsboardException {
  87 + protected SecurityUser getCurrentUser() throws ThingsboardException {
107 88 Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
108 89 if (authentication != null && authentication.getPrincipal() instanceof SecurityUser) {
109 90 return (SecurityUser) authentication.getPrincipal();
110 91 } else {
111 92 throw new ThingsboardException("You aren't authorized to perform this operation!", ThingsboardErrorCode.AUTHENTICATION);
112 93 }
113   - }*/
  94 + }
114 95 }
... ...
... ... @@ -16,51 +16,48 @@
16 16 package org.thingsboard.server.controller.plugin;
17 17
18 18 import lombok.extern.slf4j.Slf4j;
  19 +import org.springframework.beans.factory.BeanCreationNotAllowedException;
  20 +import org.springframework.beans.factory.annotation.Autowired;
  21 +import org.springframework.beans.factory.annotation.Value;
  22 +import org.springframework.security.core.Authentication;
19 23 import org.springframework.stereotype.Service;
20   -import org.springframework.web.reactive.socket.CloseStatus;
21   -import org.springframework.web.reactive.socket.WebSocketHandler;
22   -import org.springframework.web.reactive.socket.WebSocketSession;
  24 +import org.springframework.util.StringUtils;
  25 +import org.springframework.web.socket.CloseStatus;
  26 +import org.springframework.web.socket.TextMessage;
  27 +import org.springframework.web.socket.WebSocketSession;
  28 +import org.springframework.web.socket.adapter.NativeWebSocketSession;
  29 +import org.springframework.web.socket.handler.TextWebSocketHandler;
  30 +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
  31 +import org.thingsboard.server.common.data.id.CustomerId;
  32 +import org.thingsboard.server.common.data.id.TenantId;
  33 +import org.thingsboard.server.common.data.id.UserId;
  34 +import org.thingsboard.server.common.msg.tools.TbRateLimits;
  35 +import org.thingsboard.server.config.WebSocketConfiguration;
23 36 import org.thingsboard.server.service.security.model.SecurityUser;
  37 +import org.thingsboard.server.service.security.model.UserPrincipal;
  38 +import org.thingsboard.server.service.telemetry.SessionEvent;
24 39 import org.thingsboard.server.service.telemetry.TelemetryWebSocketMsgEndpoint;
  40 +import org.thingsboard.server.service.telemetry.TelemetryWebSocketService;
25 41 import org.thingsboard.server.service.telemetry.TelemetryWebSocketSessionRef;
26   -import reactor.core.publisher.Mono;
27 42
  43 +import javax.websocket.*;
28 44 import java.io.IOException;
29   -import java.security.Principal;
  45 +import java.net.URI;
  46 +import java.security.InvalidParameterException;
  47 +import java.util.Queue;
  48 +import java.util.Set;
  49 +import java.util.UUID;
  50 +import java.util.concurrent.ConcurrentHashMap;
  51 +import java.util.concurrent.ConcurrentMap;
  52 +import java.util.concurrent.LinkedBlockingQueue;
30 53
31 54 @Service
32 55 @Slf4j
33   -public class TbWebSocketHandler implements WebSocketHandler, TelemetryWebSocketMsgEndpoint {
  56 +public class TbWebSocketHandler extends TextWebSocketHandler implements TelemetryWebSocketMsgEndpoint {
34 57
35   - @Override
36   - public Mono<Void> handle(WebSocketSession session) {
37   - return session.receive()
38   - .doOnNext(message -> {
39   - Principal principal = session.getHandshakeInfo().getPrincipal().block();
40   - if (principal instanceof SecurityUser) {
41   - SecurityUser currentUser = (SecurityUser) principal;
42   - log.info("[{}][{}] Processing {}", currentUser.getTenantId(), session.getId(), message.getPayloadAsText());
43   - } else {
44   - log.info("[{}] Principal {}", session.getId(), principal);
45   - log.info("[{}] Processing {}", session.getId(), message.getPayloadAsText());
46   - }
47   - })
48   - .then();
49   - }
50   -
51   - @Override
52   - public void send(TelemetryWebSocketSessionRef sessionRef, int subscriptionId, String msg) throws IOException {
  58 + private static final ConcurrentMap<String, SessionMetaData> internalSessionMap = new ConcurrentHashMap<>();
  59 + private static final ConcurrentMap<String, String> externalSessionMap = new ConcurrentHashMap<>();
53 60
54   - }
55   -
56   - @Override
57   - public void close(TelemetryWebSocketSessionRef sessionRef, CloseStatus withReason) throws IOException {
58   -
59   - }
60   -
61   -// private static final ConcurrentMap<String, SessionMetaData> internalSessionMap = new ConcurrentHashMap<>();
62   -// private static final ConcurrentMap<String, String> externalSessionMap = new ConcurrentHashMap<>();
63   -/*
64 61 @Autowired
65 62 private TelemetryWebSocketService webSocketService;
66 63
... ... @@ -106,22 +103,6 @@ public class TbWebSocketHandler implements WebSocketHandler, TelemetryWebSocketM
106 103 }
107 104
108 105 @Override
109   - public Mono<Void> handle(WebSocketSession session) {
110   - return session.receive()
111   - .doOnNext(message -> {
112   - Principal principal = session.getHandshakeInfo().getPrincipal().block();
113   - if (principal instanceof SecurityUser) {
114   - SecurityUser currentUser = (SecurityUser) principal;
115   - log.info("[{}][{}] Processing {}", currentUser.getTenantId(), session.getId(), message.getPayloadAsText());
116   - } else {
117   - log.info("[{}] Principal {}", session.getId(), principal);
118   - log.info("[{}] Processing {}", session.getId(), message.getPayloadAsText());
119   - }
120   - })
121   - .then();
122   - }
123   -
124   - @Override
125 106 public void afterConnectionEstablished(WebSocketSession session) throws Exception {
126 107 super.afterConnectionEstablished(session);
127 108 try {
... ... @@ -410,5 +391,5 @@ public class TbWebSocketHandler implements WebSocketHandler, TelemetryWebSocketM
410 391 }
411 392 }
412 393 }
413   - */
414   -}
  394 +
  395 +}
\ No newline at end of file
... ...
1   -/**
2   - * Copyright © 2016-2019 The Thingsboard Authors
3   - *
4   - * Licensed under the Apache License, Version 2.0 (the "License");
5   - * you may not use this file except in compliance with the License.
6   - * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
10   - * Unless required by applicable law or agreed to in writing, software
11   - * distributed under the License is distributed on an "AS IS" BASIS,
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   - * See the License for the specific language governing permissions and
14   - * limitations under the License.
15   - */
16   -package org.thingsboard.server.service.security.auth.webflux;
17   -
18   -import org.springframework.beans.factory.annotation.Autowired;
19   -import org.springframework.security.authentication.ReactiveAuthenticationManager;
20   -import org.springframework.security.core.Authentication;
21   -import org.springframework.stereotype.Component;
22   -import org.thingsboard.server.service.security.auth.JwtAuthenticationToken;
23   -import org.thingsboard.server.service.security.model.SecurityUser;
24   -import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
25   -import org.thingsboard.server.service.security.model.token.RawAccessJwtToken;
26   -import reactor.core.publisher.Mono;
27   -
28   -@Component
29   -public class WebfluxAuthenticationManager implements ReactiveAuthenticationManager {
30   -
31   - @Autowired
32   - private JwtTokenFactory tokenFactory;
33   -
34   - @Override
35   - public Mono<Authentication> authenticate(Authentication authentication) {
36   - try {
37   - if (authentication.getCredentials() != null && authentication.getCredentials() instanceof RawAccessJwtToken) {
38   - RawAccessJwtToken rawAccessToken = (RawAccessJwtToken) authentication.getCredentials();
39   - SecurityUser securityUser = tokenFactory.parseAccessJwtToken(rawAccessToken);
40   - JwtAuthenticationToken auth = new JwtAuthenticationToken(securityUser);
41   - return Mono.just(auth);
42   - }
43   - return Mono.empty();
44   - } catch (Exception e) {
45   - return Mono.error(e);
46   - }
47   - }
48   -}
1   -/**
2   - * Copyright © 2016-2019 The Thingsboard Authors
3   - *
4   - * Licensed under the Apache License, Version 2.0 (the "License");
5   - * you may not use this file except in compliance with the License.
6   - * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
10   - * Unless required by applicable law or agreed to in writing, software
11   - * distributed under the License is distributed on an "AS IS" BASIS,
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   - * See the License for the specific language governing permissions and
14   - * limitations under the License.
15   - */
16   -package org.thingsboard.server.service.security.auth.webflux.jwt;
17   -
18   -import org.springframework.beans.factory.annotation.Autowired;
19   -import org.springframework.beans.factory.annotation.Qualifier;
20   -import org.springframework.http.server.reactive.ServerHttpRequest;
21   -import org.springframework.security.authentication.AuthenticationManager;
22   -import org.springframework.security.authentication.ReactiveAuthenticationManager;
23   -import org.springframework.security.core.Authentication;
24   -import org.springframework.security.core.context.SecurityContext;
25   -import org.springframework.security.core.context.SecurityContextImpl;
26   -import org.springframework.security.web.server.context.ServerSecurityContextRepository;
27   -import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
28   -import org.springframework.stereotype.Component;
29   -import org.springframework.util.StringUtils;
30   -import org.springframework.web.server.ServerWebExchange;
31   -import org.thingsboard.server.config.ThingsboardSecurityConfiguration;
32   -import org.thingsboard.server.service.security.auth.JwtAuthenticationToken;
33   -import org.thingsboard.server.service.security.auth.jwt.extractor.TokenExtractor;
34   -import org.thingsboard.server.service.security.model.token.RawAccessJwtToken;
35   -import reactor.core.publisher.Mono;
36   -
37   -import java.util.List;
38   -
39   -@Component
40   -public class JwtTokenSecurityContextRepository implements ServerSecurityContextRepository {
41   -
42   - public static final String DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME = "SPRING_SECURITY_CONTEXT";
43   -
44   - @Autowired
45   - private ReactiveAuthenticationManager webfluxAuthenticationManager;
46   -
47   - @Override
48   - public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
49   - return exchange.getSession()
50   - .doOnNext(session -> {
51   - if (context == null) {
52   - session.getAttributes().remove(WebSessionServerSecurityContextRepository.DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME);
53   - } else {
54   - session.getAttributes().put(WebSessionServerSecurityContextRepository.DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME, context);
55   - }
56   - })
57   - .flatMap(session -> session.changeSessionId());
58   - }
59   -
60   - @Override
61   - public Mono<SecurityContext> load(ServerWebExchange exchange) {
62   - ServerHttpRequest request = exchange.getRequest();
63   - String token = extractTokenFromQuery(request);
64   - if (!StringUtils.isEmpty(token)) {
65   - RawAccessJwtToken rawToken = new RawAccessJwtToken(token);
66   - Authentication auth = new JwtAuthenticationToken(rawToken);
67   - return this.webfluxAuthenticationManager.authenticate(auth).map((authentication) -> {
68   - return new SecurityContextImpl(authentication);
69   - });
70   - } else {
71   - return Mono.empty();
72   - }
73   - }
74   -
75   - private String extractTokenFromQuery(ServerHttpRequest request) {
76   - String token = null;
77   - if (request.getQueryParams() != null) {
78   - List<String> tokenParamValue = request.getQueryParams().get(ThingsboardSecurityConfiguration.JWT_TOKEN_QUERY_PARAM);
79   - if (tokenParamValue != null && !tokenParamValue.isEmpty()) {
80   - token = tokenParamValue.get(0);
81   - }
82   - }
83   - return token;
84   - }
85   -
86   -}
... ... @@ -26,7 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired;
26 26 import org.springframework.beans.factory.annotation.Value;
27 27 import org.springframework.stereotype.Service;
28 28 import org.springframework.util.StringUtils;
29   -import org.springframework.web.reactive.socket.CloseStatus;
  29 +import org.springframework.web.socket.CloseStatus;
30 30 import org.thingsboard.server.common.data.DataConstants;
31 31 import org.thingsboard.server.common.data.id.CustomerId;
32 32 import org.thingsboard.server.common.data.id.EntityId;
... ...
... ... @@ -15,7 +15,7 @@
15 15 */
16 16 package org.thingsboard.server.service.telemetry;
17 17
18   -import org.springframework.web.reactive.socket.CloseStatus;
  18 +import org.springframework.web.socket.CloseStatus;
19 19
20 20 import java.io.IOException;
21 21
... ...
... ... @@ -50,7 +50,7 @@
50 50 <commons-validator.version>1.5.0</commons-validator.version>
51 51 <commons-io.version>2.5</commons-io.version>
52 52 <commons-csv.version>1.4</commons-csv.version>
53   - <jackson.version>2.9.0</jackson.version>
  53 + <jackson.version>2.9.7</jackson.version>
54 54 <json-schema-validator.version>2.2.6</json-schema-validator.version>
55 55 <scala.version>2.11</scala.version>
56 56 <akka.version>2.4.2</akka.version>
... ... @@ -424,7 +424,7 @@
424 424 </dependency>
425 425 <dependency>
426 426 <groupId>org.springframework.boot</groupId>
427   - <artifactId>spring-boot-starter-webflux</artifactId>
  427 + <artifactId>spring-boot-starter-websocket</artifactId>
428 428 <version>${spring-boot.version}</version>
429 429 </dependency>
430 430 <dependency>
... ...