9 changed files with 54 additions and 286 deletions
@ -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(); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -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<Authentication> 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); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -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<Void> 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<SecurityContext> 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<String> tokenParamValue = request.getQueryParams().get(ThingsboardSecurityConfiguration.JWT_TOKEN_QUERY_PARAM); |
|
||||
if (tokenParamValue != null && !tokenParamValue.isEmpty()) { |
|
||||
token = tokenParamValue.get(0); |
|
||||
} |
|
||||
} |
|
||||
return token; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
Loading…
Reference in new issue