[英]How to use Spring Boot feign client for Oauth2 authentication?
[英]Spring Boot OAuth2 without web environment on Feign
我正在使用 Spring Boot 2.3.4,我需要調用需要 oauth2 身份驗證的外部 web 服務。
目前我已經通過這種方式使用 feign 實現了這一點
客戶
@FeignClient(name = "myClient", value = "myClient", url = "${app.my.client.apiUrl}", configuration = MyClientConfiguration.class)
public interface MyClient {
@GetMapping(value = "/api/my-url", consumes = "application/json")
String getSomeData();
}
客戶端配置
public class MyClientConfiguration {
private final OAuth2AuthorizedClientService oAuth2AuthorizedClientService;
private final ClientRegistrationRepository clientRegistrationRepository;
public MyClientConfiguration(OAuth2AuthorizedClientService oAuth2AuthorizedClientService, ClientRegistrationRepository clientRegistrationRepository) {
this.oAuth2AuthorizedClientService = oAuth2AuthorizedClientService;
this.clientRegistrationRepository = clientRegistrationRepository;
}
@Bean
public RequestInterceptor requestInterceptor() {
ClientRegistration clientRegistration = clientRegistrationRepository.findByRegistrationId("my-client");
AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, oAuth2AuthorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(OAuth2AuthorizedClientProviderBuilder.builder().clientCredentials().build());
return new OAuthClientCredentialsRestTemplateInterceptor(authorizedClientManager, clientRegistration);
}
}
OAuth攔截器
public class OAuthClientCredentialsRestTemplateInterceptor implements RequestInterceptor {
private static final String BEARER_HEADER_NAME = "Bearer";
private final OAuth2AuthorizedClientManager manager;
private final Authentication emptyPrincipal;
private final ClientRegistration clientRegistration;
public OAuthClientCredentialsRestTemplateInterceptor(OAuth2AuthorizedClientManager manager, ClientRegistration clientRegistration) {
this.manager = manager;
this.clientRegistration = clientRegistration;
this.emptyPrincipal = createEmptyPrincipal();
}
@Override
public void apply(RequestTemplate requestTemplate) {
OAuth2AuthorizeRequest oAuth2AuthorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(clientRegistration.getRegistrationId()).principal(emptyPrincipal).build();
OAuth2AuthorizedClient client = manager.authorize(oAuth2AuthorizeRequest);
if (client == null)
throw new IllegalStateException("Cannot retrieve a valid client for registration " + clientRegistration.getRegistrationId());
requestTemplate.header(HttpHeaders.AUTHORIZATION, BEARER_HEADER_NAME + " " + client.getAccessToken().getTokenValue());
}
private Authentication createEmptyPrincipal() {
return new Authentication() {
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.emptySet();
}
@Override
public Object getCredentials() {
return null;
}
@Override
public Object getDetails() {
return null;
}
@Override
public Object getPrincipal() {
return this;
}
@Override
public boolean isAuthenticated() {
return false;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
}
@Override
public String getName() {
return clientRegistration.getClientId();
}
};
}
}
特性
spring:
security:
oauth2:
client:
registration:
microsoft:
client-id: ******
client-secret: ******
scope: ******
authorization-grant-type: client_credentials
provider: my-client
provider:
my-client:
token-uri: ******
app:
my-client:
apiUrl: https://my-url.com
feign:
hystrix:
enabled: false
client:
config:
default:
connect-timeout: 3000
在另一個項目中,我需要相同的但它是一個沒有 web 環境的 spring 啟動應用程序,並且出現以下錯誤
bean of type 'org.springframework.security.oauth2.client.OAuth2AuthorizedClientService' that could not be found.
我該如何解決這種情況?
是否可以在沒有 tomcat(或類似)的環境中使用 oauth2 自動配置?
您需要配置一個單獨的類並告訴 spring IOC 這是無狀態會話。
@Configuration
@EnableWebSecurity
public class SecurityConfigForOauth extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().httpBasic().disable().formLogin().disable().logout().disable().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
檢查我關於如何讓 client_credentials 在https://stackoverflow.com/a/65741386/698471 上工作的回復,對 spring-boot-starter-web 沒有直接依賴
不是解決方案,只是將微服務轉換為微應用程序的解決方法:通過不使用批處理屬性或設置spring.batch.job.enabled=true然后終止進程,讓作業在應用程序啟動期間的配置時間運行。
@SpringBootApplication
public class MyBootApp implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(MyBootApp.class, args);
}
//Runs after @Configuration classes are finished synchronously including batch jobs.
@Override
public void run(String... args) throws Exception {
System.exit(0);
}
}
似乎 RestTemplate 和 WebClient 正在使用 spring-web 配置文件來自動裝配 OAuth 攔截器所需的東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.