Запустите приложение Spring Boot oAuth2 в качестве сервера ресурсов и обслуживания веб-контента - PullRequest
0 голосов
/ 13 мая 2018

Я использую Spring Boot 1.5.13 и вместе с этим Spring Security 4.2.6 и Spring Security oAuth2 2.0.15.

Я хочу найти наилучшую настройку для наших приложений Spring Boot, которые обслуживают смешанный набор контента: API REST и некоторые веб-страницы, предоставляющие удобную «целевую страницу» для разработчиков с некоторыми ссылками на них, плюс Swagger документация API, которая также является веб-контентом.

У меня есть конфигурация, которая позволяет мне запускать приложение с надлежащим потоком кода авторизации, поэтому я могу получить доступ ко всему веб-контенту через браузер и пройти проверку подлинности с помощью настроенного IdP (в моем случае PingFederate), плюс я могу выполнять вызовы API из в браузере, то есть напрямую или с клиентом REST, например с RESTClient.

Это моя конфигурация безопасности:

@Slf4j
@Configuration
@EnableWebSecurity
@EnableOAuth2Sso // this annotation must stay here!
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login**", "/webjars/**", "/css/**").permitAll()
                .antMatchers("/cfhealth").permitAll()
                .antMatchers("/").permitAll()
                .antMatchers("/protected", "/api/**").authenticated();
    }

    @Bean
    public RequestContextListener requestContextListener() {
        return new RequestContextListener();
    }

}

и конфигурация oAuth2:

@Configuration
@Slf4j
public class OAuth2Config extends ResourceServerConfigurerAdapter {

    @Value("${pingfederate.pk-uri}")
    String pingFederatePublicKeyUri;

    @Autowired
    PingFederateKeyUtils pingFederateKeyUtils;

    @Override
    public void configure(ResourceServerSecurityConfigurer config) {
        config.tokenServices(tokenServices());
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        String certificate = pingFederateKeyUtils.getKeyFromServer(pingFederatePublicKeyUri);
        String publicKey = pingFederateKeyUtils.extractPublicKey(certificate);
        converter.setVerifier(pingFederateKeyUtils.createSignatureVerifier(publicKey));
        return converter;
    }

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        return defaultTokenServices;
    }

}

Но когда я хочу вызвать REST API программно / вне браузера с токеном-носителем в заголовке, например, при использовании curl поток кода авторизации запускается и перенаправляет на локальную конечную точку входа в систему. Я хочу, чтобы вызовы API принимали маркер носителя для аутентификации без создания сеанса и чтобы все вызовы веб-содержимого / mvc в браузере устанавливали сеанс.

curl -i -H "Accept: application/json" -H "Authorization: Bearer $TOKEN" -X GET http://localhost:8080/authdemo/api/hello

Добавив аннотацию @EnableResourceServer к указанному выше классу SecurityConfig (и добавив security.oauth2.resource.filter-order = 3 в файл свойств приложения, я могу заставить команду curl работать, но тогда поток кода авторизации нарушается, Я получаю следующий вывод в браузере для всех URL в моем приложении:

<oauth> <error_description> Full authentication is required to access this resource </error_description> <error>unauthorized</error> </oauth>

Теперь есть ли способ заставить этот сценарий работать хорошо? Если да, как это будет выглядеть? Или это поддерживается только в более поздних версиях Spring Boot + Security + oAuth2?

Вопрос на Spring Boot with Security OAuth2 - как использовать сервер ресурсов с веб-формой входа в систему? очень похож

1 Ответ

0 голосов
/ 18 июня 2018

Я нашел решение: требуется несколько конфигураций HttpSecurity. Я узнал об этом, прочитав замечательную статью, написанную Мэттом Райблом в https://developer.okta.com/blog/2018/02/13/secure-spring-microservices-with-oauth, где он познакомил меня с понятием requestMatchers (.). Вот как я наконец это реализовал:

 @Configuration
 @EnableResourceServer
 @EnableWebSecurity(debug = true)
 @EnableOAuth2Sso
 public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

     @Bean
     public RequestContextListener requestContextListener() {
         return new RequestContextListener();
     }

     @Override
     public void configure(HttpSecurity http) throws Exception {
         http
             .requestMatcher(new RequestHeaderRequestMatcher("Authorization"))
             .authorizeRequests().anyRequest().fullyAuthenticated();
     }

 }

С этим я могу получить доступ к службе через браузер, что приводит к потоку кода авторизации Но доступ к API (или фактически к любой части службы) приводит к проверке предоставленного токена на предъявителя.

И чтобы проиллюстрировать, как некоторые конечные точки могут быть исключены / обнародованы в таком случае, вот как я настраиваю конечные точки привода и одну очень простую конечную точку «ping», которую я добавил сам:

 @Configuration
 @Order(1)
 public class ActuatorSecurity extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(new OrRequestMatcher(EndpointRequest.to("health", "info"),
                 new AntPathRequestMatcher("/cfhealth"))).authorizeRequests().anyRequest().permitAll();
    }

 }

И моя реализация конечной точки / cfhealth:

 @Controller
 @Slf4j
 public class MainController {

     @GetMapping(value = "/cfhealth")
     @ResponseBody
     public String cfhealth() {
         return "ok";
     }

 }

Я с удовольствием узнаю от других, является ли это наилучшим практическим способом настройки Spring Security или есть ли лучшие способы сделать это. В последние несколько недель я потратил немало времени на эту тему, и чтобы понять основные концепции Spring Security, потребовалось немало усилий.

...