Add support for the Spring Security OAuth2 native support; fixes gh-2182
This commit is contained in:
1
pom.xml
1
pom.xml
@@ -80,6 +80,7 @@
|
||||
<javax.resource-api.version>1.7.1</javax.resource-api.version>
|
||||
<cglib-nodep.version>3.3.0</cglib-nodep.version>
|
||||
<objenesis.version>3.0.1</objenesis.version>
|
||||
<!-- Deprecated - reached EOL -->
|
||||
<spring-security-oauth2.version>2.2.0.RELEASE</spring-security-oauth2.version>
|
||||
|
||||
<!-- Until we switch it to true in sc-build -->
|
||||
|
||||
@@ -153,6 +153,12 @@
|
||||
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-oauth2-client</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- BRAVE -->
|
||||
<dependency>
|
||||
|
||||
@@ -18,9 +18,11 @@ package org.springframework.cloud.sleuth.autoconfig.instrument.web.client;
|
||||
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
@@ -38,6 +40,7 @@ import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
|
||||
import org.springframework.cloud.sleuth.http.HttpClientHandler;
|
||||
import org.springframework.cloud.sleuth.instrument.web.client.HttpClientBeanPostProcessor;
|
||||
import org.springframework.cloud.sleuth.instrument.web.client.LazyTraceClientHttpRequestInterceptor;
|
||||
import org.springframework.cloud.sleuth.instrument.web.client.TraceDefaultOAuth2UserServiceCustomizer;
|
||||
import org.springframework.cloud.sleuth.instrument.web.client.TraceRequestHttpHeadersFilter;
|
||||
import org.springframework.cloud.sleuth.instrument.web.client.TraceResponseHttpHeadersFilter;
|
||||
import org.springframework.cloud.sleuth.instrument.web.client.TraceRestTemplateBeanPostProcessor;
|
||||
@@ -52,6 +55,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
|
||||
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
@@ -148,6 +152,7 @@ class TraceWebClientAutoConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ UserInfoRestTemplateCustomizer.class, OAuth2RestTemplate.class })
|
||||
@Deprecated // Use Spring-Security OAuth2 support
|
||||
protected static class TraceOAuthConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -164,4 +169,24 @@ class TraceWebClientAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(DefaultOAuth2UserService.class)
|
||||
protected static class TraceSpringSecurityOAuth2Configuration {
|
||||
|
||||
@Bean
|
||||
static BeanPostProcessor traceDefaultOAuth2UserServiceBeanPostProcessor(BeanFactory beanFactory) {
|
||||
return new BeanPostProcessor() {
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof DefaultOAuth2UserService) {
|
||||
new TraceDefaultOAuth2UserServiceCustomizer(beanFactory)
|
||||
.customize((DefaultOAuth2UserService) bean);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -152,6 +152,11 @@
|
||||
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-oauth2-client</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or 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
|
||||
*
|
||||
* https://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.springframework.cloud.sleuth.instrument.web.client;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.cloud.sleuth.instrument.web.mvc.TracingClientHttpRequestInterceptor;
|
||||
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Customizes a {@link DefaultOAuth2UserService} by providing it with a trace interceptor.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 3.0.6
|
||||
*/
|
||||
public class TraceDefaultOAuth2UserServiceCustomizer {
|
||||
|
||||
private static final Log log = LogFactory.getLog(TraceDefaultOAuth2UserServiceCustomizer.class);
|
||||
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
private static final Field REST_OPERATIONS = ReflectionUtils.findField(DefaultOAuth2UserService.class,
|
||||
"restOperations", RestOperations.class);
|
||||
|
||||
public TraceDefaultOAuth2UserServiceCustomizer(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public void customize(DefaultOAuth2UserService service) {
|
||||
try {
|
||||
ReflectionUtils.makeAccessible(Objects.requireNonNull(REST_OPERATIONS,
|
||||
"restOperations field was not found in [DefaultOAuth2UserService] class"));
|
||||
RestOperations restOperations = (RestOperations) REST_OPERATIONS.get(service);
|
||||
if (!(restOperations instanceof RestTemplate)) {
|
||||
log.warn(
|
||||
"Won't instrument the restOperations field in [DefaultOAuth2UserService] class because it's not a RestTemplate object");
|
||||
return;
|
||||
}
|
||||
RestTemplate template = (RestTemplate) restOperations;
|
||||
final TracingClientHttpRequestInterceptor interceptor = this.beanFactory
|
||||
.getBean(TracingClientHttpRequestInterceptor.class);
|
||||
new RestTemplateInterceptorInjector(interceptor).inject(template);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.warn("Can't access the restOperations field - won't instrument the [DefaultOAuth2UserService] class",
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or 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
|
||||
*
|
||||
* https://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.springframework.cloud.sleuth.instrument.web.client;
|
||||
|
||||
import org.assertj.core.api.BDDAssertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
import org.springframework.cloud.sleuth.instrument.web.mvc.TracingClientHttpRequestInterceptor;
|
||||
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
class TraceDefaultOAuth2UserServiceCustomizerTests {
|
||||
|
||||
@Test
|
||||
void should_add_a_trace_interceptor_to_defaultoauth2userservice() {
|
||||
DefaultOAuth2UserService service = new DefaultOAuth2UserService();
|
||||
BeanFactory beanFactory = beanFactory();
|
||||
TraceDefaultOAuth2UserServiceCustomizer serviceCustomizer = new TraceDefaultOAuth2UserServiceCustomizer(
|
||||
beanFactory);
|
||||
|
||||
serviceCustomizer.customize(service);
|
||||
serviceCustomizer.customize(service);
|
||||
|
||||
Object operations = ReflectionUtils
|
||||
.getField(ReflectionUtils.findField(DefaultOAuth2UserService.class, "restOperations"), service);
|
||||
BDDAssertions.then(operations).isInstanceOf(RestTemplate.class);
|
||||
RestTemplate restTemplate = (RestTemplate) operations;
|
||||
BDDAssertions.then(restTemplate.getInterceptors()).hasSize(1)
|
||||
.hasOnlyElementsOfType(TracingClientHttpRequestInterceptor.class);
|
||||
}
|
||||
|
||||
private BeanFactory beanFactory() {
|
||||
StaticListableBeanFactory beanFactory = new StaticListableBeanFactory();
|
||||
beanFactory.addBean("TracingClientHttpRequestInterceptor",
|
||||
TracingClientHttpRequestInterceptor.create(null, null));
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user