没有 Web 环境的 Spring Boot OAuth2

Posted

技术标签:

【中文标题】没有 Web 环境的 Spring Boot OAuth2【英文标题】:Spring Boot OAuth2 without web environment 【发布时间】:2021-01-16 23:28:30 【问题描述】:

我使用的是 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

在另一个项目中我需要相同的但它是一个弹簧启动应用程序没有网络环境,我有以下错误

bean of type 'org.springframework.security.oauth2.client.OAuth2AuthorizedClientService' that could not be found.

我该如何解决这种情况?

是否可以在没有 tomcat(或类似设备)的环境中使用 oauth2 自动配置?

【问题讨论】:

【参考方案1】:

你需要配置一个单独的类,告诉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);
    


【讨论】:

你好。我没有任何网络容器。所以@EnableWebSecurity 不匹配,我不能设置任何 sessionPolicy 因为我没有任何管理会话的东西【参考方案2】:

查看我关于如何让 client_credentials 在 https://***.com/a/65741386/698471 上工作的回复,对 spring-boot-starter-web 没有直接依赖

【讨论】:

以上是关于没有 Web 环境的 Spring Boot OAuth2的主要内容,如果未能解决你的问题,请参考以下文章

一款基于 Spring Boot 开发的 OA 项目,已开源,真香..

一款基于 Spring Boot 开发的 OA 项目,接私活必备!

一款基于 Spring Boot 开发的 OA 项目,接私活必备!

一款基于 Spring Boot 开发的 OA 项目,接私活必备!

一款基于 Spring Boot 开发的 OA 项目,可以学习下

一款基于 Spring Boot 开发的 OA 项目,可以学习下