Пользовательский Spring UserDetailsService не вызывается

Я пытаюсь добавить некоторые пользовательские данные для текущего пользователя, вошедшего в систему, поэтому я обнаружил, что могу реализовать свой собственный UserDetailsService и просто подключить его к Spring, но он никогда не вызывается, я всегда получаю Principal как просто строку имени пользователя.

У меня есть моя реализация UserDetailsService:

@Service
public class UserDetailServiceImpl implements UserDetailsService {

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    ...
  }
}

моя реализация UserDetails:

import org.springframework.security.core.userdetails.User;

public class LoggedInUser extends User {
...
}

и попытался установить его в конфигурации (SecurityConfiguration) несколькими способами:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
      @Autowired
      private CustomAuthenticationProvider customAuthProvider;
      @Autowired
      private UserDetailsService userDetailServiceImpl;
      @Override
      protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customAuthProvider);
        auth.userDetailsService(userDetailServiceImpl).passwordEncoder(passwordService.getPasswordEncoder());
      }
...
}

или же

@Autowired
  protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(customAuthProvider);
    auth.userDetailsService(userDetailServiceImpl).passwordEncoder(passwordService.getPasswordEncoder());
  }

или же

@Override
  @Bean
  public UserDetailsService userDetailsService() {
    return new UserDetailServiceImpl();
  }

и ничего не работает... Я попытался получить информацию о пользователе несколькими способами:

  1. в контроллере с @AuthenticationPrincipal, где я получаю ноль
  2. в службе (я получаю неверную ошибку приведения):

    Аутентификация аутентификации = SecurityContextHolder.getContext(). GetAuthentication(); (LoggedInUser) authentication.getPrincipal()

Есть идеи, почему это не работает? Мой класс impl переопределяется по умолчанию в другом месте? Я попытался посмотреть в журналах (logging.level.org.springframework.security=TRACE), но не повезло:/ Я могу войти, это работает нормально, только основные данные всегда только имя пользователя String, а не мой класс.

1 ответ

Решение

Комментарий Илья Циклона был тем, что было ключом к выяснению того, что было не так, после проверки CustomAuthenticationProvider еще раз заметил, что при возврате данных можно указать Principal это не должно быть только имя пользователя, но вы можете добавить свой кастом UserDetails там и из-за этого обычая UserDetailsService не называется, что было моей ошибкой в ​​предположении, что оно будет всегда вызываться.

Так что в конце этого достаточно, чтобы иметь кастом AuthenticationProvider с обычаем UserDetails:

@Service
public class CustomAuthenticationProvider implements AuthenticationProvider {

  @Autowired
  private UserService userService;

  @Autowired
  private PasswordService passwordService;

  @Override
  public Authentication authenticate(Authentication auth) throws AuthenticationException {
    String username = auth.getName();
    String password = auth.getCredentials().toString();

    User user = userService.getUserWithPermissionsByName(username);
    if (user == null) {
      throw new BadCredentialsException("invalid_username_or_pass");
    }

    if (!passwordService.passwordsMatch(password, user.getPassword())) {
      throw new BadCredentialsException("invalid_username_or_pass");
    }

    String[] permissions = user.getPermissions().stream().map((p) -> p.getName()).toArray(String[]::new);
    List<GrantedAuthority> grantedAuths = AuthorityUtils.createAuthorityList(permissions);
    return new UsernamePasswordAuthenticationToken(new LoggedInUser(user.getName(), user.getPassword(), true, true, true, true, grantedAuths, user.getId()),
        password, grantedAuths);
  }

  @Override
  public boolean supports(Class<?> auth) {
    return auth.equals(UsernamePasswordAuthenticationToken.class);
  }
}
Другие вопросы по тегам