【问题标题】:Spring Boot OAuth2 without web environment没有 Web 环境的 Spring Boot OAuth2
【发布时间】: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 自动配置?

【问题讨论】:

    标签: java spring spring-boot spring-security spring-security-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://stackoverflow.com/a/65741386/698471 上工作的回复,对 spring-boot-starter-web 没有直接依赖

    【讨论】:

      猜你喜欢
      • 2018-08-11
      • 1970-01-01
      • 1970-01-01
      • 2020-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-21
      • 2019-12-04
      相关资源
      最近更新 更多