spring-security Spring Security 5.7 -如何返回自定义UserDetails

j13ufse2  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(188)

我看过很多这样的例子:用户创建一个自定义的UserDetailsService,以覆盖loadUserByUsername方法并返回一个UserDetails对象的自定义实现。
这是以前用类似这样的东西做的

@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
    authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

现在有了新版本,我对如何做到这一点感到困惑
我创建了一个Bean并使用了JdbcUserDetailsManager,我可以为用户和权限表配置自定义查询

@Bean
  public UserDetailsManager userDetailsManager(DataSource dataSource) {
    String usersByUsernameQuery = "select username, password, enabled from tbl_users where username = ?";
    String authsByUserQuery = "select username, authority from tbl_authorities where username = ?";

    JdbcUserDetailsManager userDetailsManager = new JdbcUserDetailsManager(dataSource);

    userDetailsManager.setUsersByUsernameQuery(usersByUsernameQuery);
    userDetailsManager.setAuthoritiesByUsernameQuery(authsByUserQuery);

    return userDetailsManager;
  }

但是如何返回一个带有额外字段的自定义UserDetails对象,例如带有新版本的电子邮件?

xoshrz7s

xoshrz7s1#

好的,经过多次尝试,我所做的是从我的自定义SecurityConfig类中完全删除JdbcUserDetailsManager的东西,我创建了一个自定义UserDetailsService和自定义UserDetails类,它工作了。
所以安全配置类没有关于用户身份验证的代码。我很困惑,因为我认为我必须在配置类中创建一个@Bean,自己实现身份验证,通常所有的身份验证代码都必须在配置类中完成,但它使用这种方法工作。

@Service
public class MyCustomUserDetailsService implements UserDetailsService {

  @Autowired
  UserRepository userRepository;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userRepository.findByUsername(username);

    if (user == null) {
      throw new UsernameNotFoundException("User Not Found with username: " + username);
    }
    return MyUserDetails.build(user);
  }
}

而细节类

public class MyUserDetails implements UserDetails {

  private String username;
  private String firstName;
  private String lastName;

  @JsonIgnore
  private String password;

  private Collection<? extends GrantedAuthority> authorities;

  public MyUserDetails(String username, String firstName, String lastName, String password,
      Collection<? extends GrantedAuthority> authorities) {
    this.username = username;
    this.firstName = firstName;
    this.lastName = lastName;
    this.password = password;
    this.authorities = authorities;
  }

  public static MyUserDetails build(User user) {
    List<GrantedAuthority> authorities = user.getRoles().stream()
        .map(role -> new SimpleGrantedAuthority(role.getAuthority()))
        .collect(Collectors.toList());

    return new MyUserDetails(
        user.getUsername(), 
        user.getFirstName(),
        user.getLastName(),
        user.getPassword(), 
        authorities);
  }

  @Override
  public Collection<? extends GrantedAuthority> getAuthorities() {
    return authorities;
  }

  public String getFirstName() {
    return firstName;
  }

  public String getLastName() {
    return lastName;
  }

  @Override
  public String getPassword() {
    return password;
  }

  @Override
  public String getUsername() {
    return username;
  }

  @Override
  public boolean isAccountNonExpired() {
    return true;
  }

  @Override
  public boolean isAccountNonLocked() {
    return true;
  }

  @Override
  public boolean isCredentialsNonExpired() {
    return true;
  }

  @Override
  public boolean isEnabled() {
    return true;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o)
      return true;
    if (o == null || getClass() != o.getClass())
      return false;
    MyUserDetails user = (MyUserDetails) o;

    return Objects.equals(username, user.username);
  }
}

同时检查Spring Security Architecture

相关问题