我正在开发一个基本应用程序,该应用程序应在spring数据休息的帮助下生成用于不同实体的一些标准休息端点。端点应仅对具有特定角色的用户可用(通过Spring Security)。
现在,我的用户详细信息服务从数据库加载信息,以便在身份验证期间创建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);
}
它可以工作,但是我的端点当然对所有人开放。
问题