对于最新的稳定版本,请使用 Spring Security 7.0.4spring-doc.cadn.net.cn

内存认证

Spring Security 的 InMemoryUserDetailsManager 实现了 UserDetailsService,以支持基于内存存储的用户名/密码身份验证。 InMemoryUserDetailsManager 通过实现 UserDetailsManager 接口来管理 UserDetails。 当 Spring Security 配置为 接受用户名和密码 进行身份验证时,会使用基于 UserDetails 的身份验证。spring-doc.cadn.net.cn

在下面的示例中,我们使用 Spring Boot CLI 对密码值 password 进行编码,并得到编码后的密码 {bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klWspring-doc.cadn.net.cn

InMemoryUserDetailsManager Java 配置
@Bean
public UserDetailsService users() {
	UserDetails user = User.builder()
		.username("user")
		.password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
		.roles("USER")
		.build();
	UserDetails admin = User.builder()
		.username("admin")
		.password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
		.roles("USER", "ADMIN")
		.build();
	return new InMemoryUserDetailsManager(user, admin);
}
<user-service>
	<user name="user"
		password="{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW"
		authorities="ROLE_USER" />
	<user name="admin"
		password="{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW"
		authorities="ROLE_USER,ROLE_ADMIN" />
</user-service>
@Bean
fun users(): UserDetailsService {
    val user = User.builder()
        .username("user")
        .password("{bcrypt}$2a$10\$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
        .roles("USER")
        .build()
    val admin = User.builder()
        .username("admin")
        .password("{bcrypt}$2a$10\$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
        .roles("USER", "ADMIN")
        .build()
    return InMemoryUserDetailsManager(user, admin)
}

前面的示例以安全格式存储密码,但在入门体验方面仍有诸多不足。spring-doc.cadn.net.cn

在以下示例中,我们使用 User.withDefaultPasswordEncoder 来确保内存中存储的密码受到保护。 然而,它并不能防止通过反编译源代码来获取密码。 因此,User.withDefaultPasswordEncoder 仅应用于“入门”阶段,不适用于生产环境。spring-doc.cadn.net.cn

使用 User.withDefaultPasswordEncoder 的 InMemoryUserDetailsManager
@Bean
public UserDetailsService users() {
	// The builder will ensure the passwords are encoded before saving in memory
	UserBuilder users = User.withDefaultPasswordEncoder();
	UserDetails user = users
		.username("user")
		.password("password")
		.roles("USER")
		.build();
	UserDetails admin = users
		.username("admin")
		.password("password")
		.roles("USER", "ADMIN")
		.build();
	return new InMemoryUserDetailsManager(user, admin);
}
@Bean
fun users(): UserDetailsService {
    // The builder will ensure the passwords are encoded before saving in memory
    val users = User.withDefaultPasswordEncoder()
    val user = users
        .username("user")
        .password("password")
        .roles("USER")
        .build()
    val admin = users
        .username("admin")
        .password("password")
        .roles("USER", "ADMIN")
        .build()
    return InMemoryUserDetailsManager(user, admin)
}

没有简单的方法在基于 XML 的配置中使用 User.withDefaultPasswordEncoder。 对于演示或刚入门的情况,你可以选择在密码前加上 {noop} 前缀,以表示不应使用任何编码spring-doc.cadn.net.cn

<user-service> {noop} XML 配置
<user-service>
	<user name="user"
		password="{noop}password"
		authorities="ROLE_USER" />
	<user name="admin"
		password="{noop}password"
		authorities="ROLE_USER,ROLE_ADMIN" />
</user-service>