概述
UserDetailsServiceAutoConfiguration的作用是在内存中配置一个用户信息管理者,通俗的讲就是自动为我们生成一个用户,就是平时我们直接启动一个spring-security项目,控制台会打印一串密码,这个密码就是自动生成的用户信息
UserDetailsServiceAutoConfiguration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
   | @Configuration @ConditionalOnClass(AuthenticationManager.class) @ConditionalOnBean(ObjectPostProcessor.class) @ConditionalOnMissingBean({ AuthenticationManager.class, AuthenticationProvider.class, UserDetailsService.class }) 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; 	}
  }
 
   | 
 
- 判断类路径存在AuthenticationManager,满足条件
 
- 判断spring容器中存在ObjectPostProcessor实例,在SecurityAutoConfiguration一文分析中我们知道最终容器中注册了一个AutowireBeanFactoryObjectPostProcessor,满足条件
 
- 判断spring容器中不存在AuthenticationManager、AuthenticationProvider、UserDetailsService这三个类的实例,默认我们没有自定义这三个类,满足条件
 
综上,满足所有条件,将UserDetailsServiceAutoConfiguration实例注册到spring容器中
InMemoryUserDetailsManager
- 判断sprng容器中不存在org.springframework.security.oauth2.client.registration.ClientRegistrationRepository实例,我们没有依赖oauth2,满足条件
 
最终将InMemoryUserDetailsManager注册到spring容器中,InMemoryUserDetailsManager内的用户信息是自动生成的,可以发现这个user对象是在SecurityProperties中获取的
SecurityProperties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
   | @ConfigurationProperties(prefix = "spring.security") public class SecurityProperties {
  	public static final int BASIC_AUTH_ORDER = Ordered.LOWEST_PRECEDENCE - 5;
  	public static final int IGNORED_ORDER = Ordered.HIGHEST_PRECEDENCE;
  	public static final int DEFAULT_FILTER_ORDER = OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER - 100; 	 	private final Filter filter = new Filter(); 	 	private User user = new User();
  	public User getUser() { 		return this.user; 	}
  	public Filter getFilter() { 		return this.filter; 	}
  	public static class Filter {
  		
 
  		private int order = DEFAULT_FILTER_ORDER;
  		
 
  		private Set<DispatcherType> dispatcherTypes = new HashSet<>( 				Arrays.asList(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST));
  		public int getOrder() { 			return this.order; 		}
  		public void setOrder(int order) { 			this.order = order; 		}
  		public Set<DispatcherType> getDispatcherTypes() { 			return this.dispatcherTypes; 		}
  		public void setDispatcherTypes(Set<DispatcherType> dispatcherTypes) { 			this.dispatcherTypes = dispatcherTypes; 		}
  	}
  	public static class User {
  		 		private String name = "user";
  		 		private String password = UUID.randomUUID().toString();
  		 		private List<String> roles = new ArrayList<>(); 		 		private boolean passwordGenerated = true;
  		public String getName() { 			return this.name; 		}
  		public void setName(String name) { 			this.name = name; 		}
  		public String getPassword() { 			return this.password; 		}
  		public void setPassword(String password) { 			if (!StringUtils.hasLength(password)) { 				return; 			} 			this.passwordGenerated = false; 			this.password = password; 		}
  		public List<String> getRoles() { 			return this.roles; 		}
  		public void setRoles(List<String> roles) { 			this.roles = new ArrayList<>(roles); 		}
  		public boolean isPasswordGenerated() { 			return this.passwordGenerated; 		}
  	}
  }
   | 
 
默认生成的用户名是user,密码是随机的uuid,没有任何角色信息
总结
UserDetailsServiceAutoConfiguration自动在当前内存中配置了一个用户名为user密码为随机uuid的用户信息,密码可以在控制台找到,这是默认的配置,不过如果我们自定义了AuthenticationManager、AuthenticationProvider、UserDetailsService这三个类,就不会为我们生成默认的用户信息了