我见过很多用户创建自定义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
对象与一个额外的字段,例如电子邮件与新版本?
OK,经过多次尝试,我所做的是从我的自定义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);
}
}
和details类
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