Я работаю над базовым приложением, которое должно генерировать - с помощью упругости данных пружины - некоторые стандартные конечные точки отдыха для разных объектов.Конечные точки должны быть доступны только для пользователей с определенной ролью (с помощью весенней защиты).
В данный момент моя служба пользовательских данных загружает информацию из базы данных для создания UserDetails
объектов во время аутентификации.
@Service
public class MyUserDetailsService implements UserDetailsService {
@Setter(onMethod=@__({@Autowired}))
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException(username));
return org.springframework.security.core.userdetails.User.builder()
.username(user.getUsername())
.password(user.getPassword())
.roles(user.getRoles())
.build();
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Теперь я пытаюсь обеспечить безопасность на уровне метода для моих конечных точек.
@PreAuthorize("hasRole('USER')")
public interface UserRepository extends JpaRepository<User, Long> {
@PreAuthorize("permitAll()")
Optional<User> findByUsername(String username);
}
Проблема в том, что loadUserByUsername
явно используется во время аутентификации.В методе я использую метод findByUsername
, описанный выше.Даже если он настроен на permitAll()
, он все равно пытается что-то сделать с SecurityContext
.По крайней мере, я получаю следующую ошибку при попытке доступа к конечной точке:
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
Я думаю, что в настоящее время я нахожусь в процессе создания SecurityContext, и поэтому он все еще пуст.
Если я изменю свой репозиторий на
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
, он будет работать, но тогда мои конечные точки будут открыты для всех.
Вопросы
- Есть ли что-то принципиально неправильное в том, что я делаю?
- Если нет, как я могу обойти эту проблему?