我从哪里获取 Spring 安全中的"username"值以传递给用户详细信息服务接口的加载用户按用户名(字符串用户名)方法



我正试图通过基于用户名和密码对用户进行身份验证来从数据库获取用户。我使用的是基本身份验证。我在rest api的授权头中发送用户名和密码

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

@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类实现UserDetailsService并覆盖loadUserByUsername方法,该方法需要将用户名作为参数传递。我的问题是:我如何将用户名传递给loadUserByUsername()方法从我的UserService类,我从我的控制器调用。用户名值驻留在哪里?我的理解是-身份验证对象包含用户凭据,当用户输入他们的凭据并发送他们的请求时传递给身份验证对象,我如何检索这个用户名值

@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,因此您的安全类看起来像这样:

@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类中的身份验证以满足业务需求,如下面的示例:

@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:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String name);
}

最新更新