我从哪里获取 spring 安全性中的 "username" 值以传递给 UserDetailsS​​ervice 接口的 loadUserByUsername(String username) 方法

where do I get the "username" value from in spring security to pass to the loadUserByUsername(String username) method of UserDetailsService interface

我正在尝试通过基于用户名和密码对用户进行身份验证来从数据库中获取用户。我正在使用基本身份验证来执行此操作。 我在授权 header 中发送用户名和密码,其余 api

在我的控制器中,getUser() 方法调用 UserService 的 getuser() 方法 class

 @GetMapping("/user/self")
public ResponseEntity<UserDto> getUser() {
    UserDto UserDto = userService.getUser();
    return new ResponseEntity<>(UserDto, HttpStatus.OK);
}

@PutMapping("/user/self")
public ResponseEntity<User> updateUser(@Valid @RequestBody Map<String, String> userMap, Principal principal) {
    String username = principal.getName();
    String firstname = userMap.get("firstName");
    String lastName = userMap.get("lastName");
    String password = BCrypt.hashpw(userMap.get("password"), BCrypt.gensalt(10));
    User user = userService.getUserByUserName(username);
    user.setFirstName(firstname);
    user.setLastName(lastName);
    user.setPassword(password);
    userService.save(user);
    return new ResponseEntity<>(user, HttpStatus.NO_CONTENT);
}

UserService class 实现 UserDetailsS​​ervice 并覆盖需要将用户名作为参数传递的 loadUserByUsername 方法。我的问题是:如何将用户名从我从我的控制器调用的 UserService class 传递给 loadUserByUsername() 方法。用户名值在哪里? 我的理解是 - 身份验证 Object 包含传递给身份验证 object 的用户凭据,当用户键入他们的凭据并发送他们的请求时,我如何检索此用户名值

 @Service
     public class UserService implements UserDetailsService {

@Autowired
UserRepository userRepository;

public UserDto save(User user) {
    String hashedPassword = BCrypt.hashpw(user.getPassword(), BCrypt.gensalt(10));
    user.setPassword(hashedPassword);
    userRepository.save(user);
    UserDto userDto = new UserDto();
    userDto.setId(user.getId());
    userDto.setFirstName(user.getFirstName());
    userDto.setLastName(user.getLastName());
    userDto.setUserName(user.getUserName());
    userDto.setAccountUpdatedAt(user.getAccountUpdatedAt());
    userDto.setAccountCreatedAt(user.getAccountCreatedAt());
    return userDto;
}

@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
    User user = userRepository.findByUserName(userName);
    if (user == null) {
        throw new UsernameNotFoundException(userName + "was not found");
    }
    return new UserPrincipal(user);
}

这是我的存储库代码:

 @Repository
    public interface UserRepository extends CrudRepository<User, Long> {

User findByUserName(String userName);
   }

这是我的验证码:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
DataSource dataSource;
@Autowired
private AuthenticationEntryPoint authenticationEntryPoint;
@Autowired
UserService userService;


@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(passwordEncoder());

}


@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().csrf().disable();
    http.authorizeRequests().antMatchers("/v1/user").permitAll()
            .antMatchers("/v1/user/self").authenticated().and().httpBasic()
            .authenticationEntryPoint(authenticationEntryPoint);
 }
}

如果你处理 JPA 那么在你的情况下你必须使用 userDetailsService 而不是 jdbcauthentication,因此你的安全性 class 看起来像这样:

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private  UserService userService;
    
    public SecurityConfig(UserService userService){
        this.userService = userService;
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder(10); // Number of rounds 
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(this.userService).passwordEncoder(passwordEncoder());
    }
}

然后您可以在 UserService class 中自定义身份验证以满足业务需求,如下例所示:

@Service
public class UserService implements UserDetailsService {

    private final UserRepository userRepository;
    
    public UserService(UserRepository userRepository){
        this.userRepository = userRepository;
    }

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

        Optional<User> user = userRepository.findByUsername(username);

        if(user.isPresent()){
            log.info("cretaed under User service : " + user.get());
            return user.get();
        }

        throw new UsernameNotFoundException("empty or invalud user");
    }
}

此外,不要忘记在您的存储库中创建 findByUsername 方法,也不要忘记在您的模块中实现 org.springframework.security.core.userdetails.UserDetails class:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    Optional<User> findByUsername(String name);
}