一、用户
public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities(); // 权限标识集合
String getPassword(); // 密码
String getUsername(); // 用户名
boolean isAccountNonExpired(); // 是否未过期
boolean isAccountNonLocked(); // 是否未锁定
boolean isCredentialsNonExpired(); // 密码是否未过期
boolean isEnabled(); // 是否可用
}
1.1 用户类的自定义
当我们要实现自己的用户类时,我们可以继承UserDetails子类User
public class MyUserDetails extends User {
private static final long serialVersionUID = 3899399998765880053L;
private String id;
public MyUserDetails(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
public MyUserDetails(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
}
//忽略id的get和set方法
}
二、操作用户
public interface UserDetailsService {
// 通过 username 查询 UerDetails
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
2.1 默认的UserDetailsService
默认UserDetailsService是InMemoryUserDetailsManager,其注册在UserDetailsServiceAutoConfiguration中
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(AuthenticationManager.class)
@ConditionalOnBean(ObjectPostProcessor.class)
@ConditionalOnMissingBean(
value = { AuthenticationManager.class, AuthenticationProvider.class, UserDetailsService.class },
type = { "org.springframework.security.oauth2.jwt.JwtDecoder",
"org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector" })
public class UserDetailsServiceAutoConfiguration {
private static final String NOOP_PASSWORD_PREFIX = "{noop}";
private static final Pattern PASSWORD_ALGORITHM_PATTERN = Pattern.compile("^\\{.+}.*$");
private static final Log logger = LogFactory.getLog(UserDetailsServiceAutoConfiguration.class);
@Bean
@ConditionalOnMissingBean(
type = "org.springframework.security.oauth2.client.registration.ClientRegistrationRepository")
@Lazy
public InMemoryUserDetailsManager inMemoryUserDetailsManager(SecurityProperties properties,
ObjectProvider<PasswordEncoder> passwordEncoder) {
SecurityProperties.User user = properties.getUser();
List<String> roles = user.getRoles();
return new InMemoryUserDetailsManager(
User.withUsername(user.getName()).password(getOrDeducePassword(user, passwordEncoder.getIfAvailable()))
.roles(StringUtils.toStringArray(roles)).build());
}
private String getOrDeducePassword(SecurityProperties.User user, PasswordEncoder encoder) {
String password = user.getPassword();
if (user.isPasswordGenerated()) {
logger.info(String.format("%n%nUsing generated security password: %s%n", user.getPassword()));
}
if (encoder != null || PASSWORD_ALGORITHM_PATTERN.matcher(password).matches()) {
return password;
}
return NOOP_PASSWORD_PREFIX + password;
}
}
2.2 UserDetailsService是自定义
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List<SimpleGrantedAuthority> simpleGrantedAuthorityList = new ArrayList<>();
//这里面模拟从数据库获取用户信息
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("ROLE_admin");
simpleGrantedAuthorityList.add(simpleGrantedAuthority);
return new MyUserDetails("user",passwordEncoder.encode("123"), simpleGrantedAuthorityList);
}
}
把自定义的MyUserDetailsService注册到Spring Security中
@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
@Bean
public MyUserDetailsService myUserDetailsService(){
return new MyUserDetailsService();
}
}
只要我们把他注册到容器中,Spring Security机会获取它。具体原因如下
@Configuration(proxyBeanMethods = false)
@Import(ObjectPostProcessorConfiguration.class)
public class AuthenticationConfiguration {
@Bean
public static InitializeUserDetailsBeanManagerConfigurer initializeUserDetailsBeanManagerConfigurer(ApplicationContext context) {
return new InitializeUserDetailsBeanManagerConfigurer(context);
}
}
@Order(InitializeUserDetailsBeanManagerConfigurer.DEFAULT_ORDER)
class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationConfigurerAdapter {
// 忽略代码........
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
//创建其内部类InitializeUserDetailsManagerConfigurer
auth.apply(new InitializeUserDetailsManagerConfigurer());
}
class InitializeUserDetailsManagerConfigurer extends GlobalAuthenticationConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
if (auth.isConfigured()) {
return;
}
//从容器中获取UserDetailsService,如果没有直接返回
UserDetailsService userDetailsService = getBeanOrNull( UserDetailsService.class);
if (userDetailsService == null) {return;}
//从容器中获取PasswordEncoder
PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
//从容器中获取UserDetailsPasswordService
UserDetailsPasswordService passwordManager = getBeanOrNull(UserDetailsPasswordService.class);
//创建DaoAuthenticationProvider,将3个类配置进去
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
if (passwordEncoder != null) {
provider.setPasswordEncoder(passwordEncoder);
}
if (passwordManager != null) {
provider.setUserDetailsPasswordService(passwordManager);
}
provider.afterPropertiesSet();
auth.authenticationProvider(provider);
}
}
}