Почему Spring не использует мой компонент PrincipalExtractor? - PullRequest
2 голосов
/ 15 апреля 2019

Spring не хочет использовать мой PrincipalExtractor боб. Вместо этого он использует значение по умолчанию FixedPrincipalExtractor.

Я пытаюсь следовать руководству Spring для OAuth2: https://spring.io/guides/tutorials/spring-boot-oauth2/

И все прошло почти нормально, пока я не решил сохранить аутентифицированного пользователя в моей базе данных. В учебнике просто говорится: «Это слишком просто, поэтому мы не будем показывать, как это сделать». Конечно, это момент, когда я застрял на несколько дней.

Есть WebSecurityConfig класс. Это беспорядок, но он используется в образовательных целях.

@Configuration
@EnableWebSecurity
@EnableOAuth2Client
@RestController
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    OAuth2ClientContext oauth2ClientContext;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .antMatcher("/**")
                .authorizeRequests()
                .antMatchers("/", "/login**", "/js/**", "/error**", "/webjars/**").permitAll()
                .anyRequest().authenticated()
                .and().logout().logoutSuccessUrl("/").permitAll()
                .and()
                .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .and()
                .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);

    }

    private Filter ssoFilter() {
        CompositeFilter filter = new CompositeFilter();
        List<Filter> filters = new ArrayList<>();
        filters.add(ssoFilter(google(), "/login/google"));
        filter.setFilters(filters);

        return filter;
    }

    private Filter ssoFilter(ClientResources client, String path) {
        OAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationFilter = new OAuth2ClientAuthenticationProcessingFilter(path);
        OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
        oAuth2ClientAuthenticationFilter.setRestTemplate(oAuth2RestTemplate);
        UserInfoTokenServices tokenServices = new UserInfoTokenServices(client.getResource().getUserInfoUri(),
                client.getClient().getClientId());
        tokenServices.setRestTemplate(oAuth2RestTemplate);
        oAuth2ClientAuthenticationFilter.setTokenServices(tokenServices);

        return oAuth2ClientAuthenticationFilter;
    }

    @Bean
    @ConfigurationProperties("google")
    public ClientResources google() {
        return new ClientResources();
    }

    @Bean
    public FilterRegistrationBean<OAuth2ClientContextFilter> oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
        FilterRegistrationBean<OAuth2ClientContextFilter> registration = new FilterRegistrationBean<OAuth2ClientContextFilter>();
        registration.setFilter(filter);
        registration.setOrder(-100);

        return registration;
    }

    @Bean
    public PrincipalExtractor principalExtractor(UserDetailsRepo userDetailsRepo) {
        return map -> {
            String id = (String) map.get("sub");
            User user = userDetailsRepo.findById(id).orElseGet(() -> {
                User newUser = new User();

                newUser.setId(id);
                newUser.setEmail((String) map.get("email"));
                // and so on...

                return newUser;
            });

            return userDetailsRepo.save(user);
        };
    }
}

class ClientResources {

    @NestedConfigurationProperty
    private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();

    @NestedConfigurationProperty
    private ResourceServerProperties resource = new ResourceServerProperties();

    public AuthorizationCodeResourceDetails getClient() {
        return client;
    }

    public ResourceServerProperties getResource() {
        return resource;
    }
}

И application.yml:

spring:
  datasource:
    url: jdbc:postgresql://localhost/my_db
    username: postgres
    password: password
  jpa:
    generate-ddl: true
    properties:
      hibernate:
        jdbc:
          lob:
            non_contextual_creation: true

google:
  client:
    clientId: 437986124027-7072jmbsba04d11fft0h9megkqcpem2t.apps.googleusercontent.com
    clientSecret: ${clientSecret}
    accessTokenUri: https://www.googleapis.com/oauth2/v4/token
    userAuthorizationUri: https://accounts.google.com/o/oauth2/v2/auth
    clientAuthenticationScheme: form
    scope: openid,email,profile
  resource:
    userInfoUri: https://www.googleapis.com/oauth2/v3/userinfo
    preferTokenInfo: true

Как я писал выше, Spring на самом деле не хочет использовать мой bean-компонент PrincipalExtractor и вместо него использует стандартный FixedPrincipalExtractor. Я потратил много времени, пытаясь решить эту проблему, но ничего не помогает. За исключением изменения application.yml, например:

security:
  oauth2:
    client:
      clientId: 620652621050-v6a9uqrjq0ejspm5oqbek48sl6od55gt.apps.googleusercontent.com
      clientSecret: ${clientSecret}
  [...]
    resource:
      userInfoUri: https://www.googleapis.com/oauth2/v3/userinfo
      preferTokenInfo: true

Было google.client.clientId и оно меняется на security.oauth2.client.clientId, как вы можете видеть.

И если вы удалите все методы фильтра и все, что с ними связано, то это сработает, да. Это действительно использует мой PrincipleExtractor. Но как я могу добавить больше провайдеров аутентификации (Facebook, GitHub и т. Д.) И локальной аутентификации сейчас?

Наконец, у меня есть несколько вопросов:

  1. Как заставить Spring использовать мой PrincipalExtractor?
  2. Должен ли я вообще использовать PrincipalExtractor? Может быть, есть другой способ сделать то же самое?
  3. Что-то не так с моим application.yml?

То, что я пробовал:

  1. Добавление сервера @EnableAuthorizationServer ( Почему мой источник @bean никогда не создается? )

Ничего не меняется.

  1. Добавление ResourceServerTokenServices ( ОсновныеExtractor и AuthoritiesExtractor не попадают )

Spring не может найти UserInfoRestTemplateFactory. Я полагаю, что добавлять бин вручную неправильно, просто не работает.

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