Понимание Spring Security @ EnableOAuth2Client аннотация - PullRequest
1 голос
/ 01 апреля 2019

У меня проблема с реализацией OpenID connect на основе библиотеки Spring Security Oauth2.(Подробнее о проблеме читайте в отдельном вопросе .) Во время исследования я прочитал документацию для аннотации @EnableOauth2Client , в которой говорится:

Включите настройку для клиента OAuth2 в веб-приложении, которое использует Spring Security и хочет использовать Предоставление кода авторизации от одного или нескольких серверов авторизации OAuth2.Чтобы воспользоваться этой возможностью, вам нужен глобальный фильтр сервлетов в вашем приложении DelegatingFilterProxy, который делегирует bean-компоненту с именем «oauth2ClientContextFilter».Когда этот фильтр установлен, ваше клиентское приложение может использовать другой компонент, предоставленный этой аннотацией (AccessTokenRequest), для создания OAuth2RestTemplate, например,

@Configuration
@EnableOAuth2Client
public class RemoteResourceConfiguration {

    @Bean
    public OAuth2RestOperations restTemplate(OAuth2ClientContext oauth2ClientContext) {
           return new OAuth2RestTemplate(remote(), oauth2ClientContext);
    }

}

Клиентским приложениям, использующим предоставления учетных данных клиента, не требуется AccessTokenRequest илиОграниченные RestOperations (состояние является глобальным для приложения), но они все равно должны использовать фильтр для запуска OAuth2RestOperations для получения токена, когда это необходимо.Приложения, которые используют [sic] для предоставления пароля, должны установить свойства аутентификации в OAuth2ProtectedResourceDetails перед использованием RestOperations, и это означает, что сами данные ресурса также должны быть за сеанс (при условии, что в системе несколько пользователей)).

A Примечание о версиях и документации: эта документация является версией 2.0.4, и все, что связано со страницей проекта Spring Security даже для более новой версии2.3.5 ссылка, которую использует мой проект.Другие наши версии Spring: Spring Boot 1.3.0, Spring Security 3.2.5, Spring Framework 4.2.3.

Я не совсем понимаю, что это значит, особенно

aГлобальный фильтр сервлетов в вашем приложении DelegatingFilterProxy, который делегирует bean-компоненту с именем «oauth2ClientContextFilter»

Вот как мы настраиваем наш шаблон отдыха.

@Configuration
@EnableOAuth2Client
public class OpenIdConnectConfig {

    @Bean
    public OAuth2ProtectedResourceDetails openIdResourceDetails() {
        AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
        details.setClientId(clientId);
        details.setClientSecret(clientSecret);
        details.setAccessTokenUri(accessTokenUri);
        details.setUserAuthorizationUri(userAuthorizationUri);
        details.setClientAuthenticationScheme(AuthenticationScheme.form);
        details.setScope(oidcScopes);
        details.setPreEstablishedRedirectUri(redirectUri);
        details.setUseCurrentUri(false);
        return details;
    }

    @Bean(name = "my.company.ui.security.OpenIdRestTemplate")
    // ToDo: fix org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'session' is not active for the current thread
    public OAuth2RestTemplate OpenIdRestTemplate(OAuth2ClientContext clientContext) {
        return new OAuth2RestTemplate(openIdResourceDetails(), clientContext);
    }

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

    @Value("${oidc.clientId}")
    private String clientId;

    @Value("${oidc.clientSecret}")
    private String clientSecret;

    @Value("${oidc.accessTokenUrl}")
    private String accessTokenUri;

    @Value("${oidc.userAuthorizationUri}")
    private String userAuthorizationUri;

    @Value("${oidc.redirectUri}")
    private String redirectUri;

    @Value("#{'${oidc.scopes}'.split(',')}")
    private List<String> oidcScopes;
}

Фильтр, который выполняетаутентификация (некоторая обработка исключений и пользовательский код обработки удалены):

public class OpenIdConnectFilter extends AbstractAuthenticationProcessingFilter {

    public OpenIdConnectFilter(
            RequestMatcher requiresAuthenticationRequestMatcher,
            AuthenticationService authenticationService
    ) {
        super(requiresAuthenticationRequestMatcher);
        setAuthenticationManager(new NoopAuthenticationManager());
    }

    @SuppressWarnings("RedundantThrows") // Matching overridden method
    @Override
    public Authentication attemptAuthentication(
            HttpServletRequest request,
            HttpServletResponse response
    ) throws AuthenticationException, IOException, ServletException {

        // Required parameters (one-time access code, state) are retrieved from the context
        OAuth2AccessToken oAuth2AccessToken = restTemplate.getAccessToken();

        // Process the token, get the user details, return an Authentication object.
    }

    public void setRestTemplate(OAuth2RestTemplate restTemplate) {
        this.restTemplate = restTemplate;

    }

    private static class NoopAuthenticationManager implements AuthenticationManager {

        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            throw new UnsupportedOperationException("No authentication should be done with this AuthenticationManager");
        }

    }


    private static final Logger LOGGER = LoggerFactory.getLogger(OpenIdConnectFilter.class);

    @Value("${oidc.clientId}")
    private String clientId;

    @Value("${oidc.issuer}")
    private String issuer;

    @Value("${oidc.jwt.jwk.url}")
    private String jwkUrl;

    private final AuthenticationService authenticationService;

    private OAuth2RestTemplate restTemplate;
}

и настройка безопасности, которая устанавливает Spring Security FilterProxyChain:

@Configuration
@EnableWebSecurity
@EnableOAuth2Client
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    @Override
    @SuppressWarnings("unchecked")
    protected void configure(HttpSecurity http)
            throws Exception {

        http
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
            .and()
            .csrf()
                .disable()
            .authorizeRequests()
                .expressionHandler(securityExpressionHandler)
                .antMatchers("/asset/**").access("permitAll")
                .antMatchers("/ws/ssoEnabled").access("permitAll")
                .antMatchers("/**").access("hasRole('ROLE_USER') or hasRole('ROLE_TOKEN_ACCESS')")
                .and()
            .httpBasic()
                .authenticationEntryPoint(ajaxAwareLoginUrlAuthenticationEntryPoint)
                .and()
            // Handles unauthenticated requests, catching UserRedirectRequiredExceptions and redirecting to OAuth provider
            .addFilterAfter(new OAuth2ClientContextFilter(), SecurityContextPersistenceFilter.class)
            // Handles the oauth callback, exchanging the one-time code for a durable token
            .addFilterAfter(openIdConnectFilter, OAuth2ClientContextFilter.class)
            .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/logincheck")
                .usernameParameter("username")
                .passwordParameter("password")
                .successHandler(ajaxAwareAuthenticationSuccessHandler)
                .failureHandler(ajaxAwareAuthenticationFailureHandler)
                .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login")
                .and()
            .rememberMe()
                .rememberMeServices(rememberMeServices)
                // Even though this key has been added directly to the rememberMeServices instance, the RememberMeConfigurer
                // can instantiate a new RememberMeServices with a made-up key if the same key is not provided.
                .key("the key value")
        ;

        // We do not configure a bean for the SessionAuthenticationStrategy. We want to use the Spring default strategy,
        // which is configured by the above builder chain. In order to share the correct, configured instance with our
        // custom OpenIdConnectFilter, we first tell the builder to perform the configuration (normally this would be
        // done long after this method returns)...
        http.getConfigurer(SessionManagementConfigurer.class).init(http);
        // ... then we get the shared object by interface (SessionAuthenticationStrategy) class name...
        final SessionAuthenticationStrategy sessionAuthenticationStrategy = http.getSharedObject(SessionAuthenticationStrategy.class);
        // ... then set it in our custom filter.
        openIdConnectFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);
    }
}

Вы заметите несколько механизмов аутентификациитам.Мы находимся в процессе перехода от формы входа в систему к имени пользователя Oauth, и для первоначального выпуска установлен флаг функции.Флаг работает довольно хорошо, за исключением проблемы, описанной в моем связанном вопросе вверху, которая возникает некоторое время после переключения флага, а затем, похоже, разрешается сама собой.


Конфигурация, которую я имеюВыше показано достаточное выполнение задокументированных инструкций для аннотации @EnableOauth2Client?

Или есть что-то еще, что мне нужно сделать с DelegationFilterProxy?Если да, то как?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...