In-Memory Authentication

Spring Security 的 InMemoryUserDetailsManager 实现 UserDetailsService,以提供对存储在内存中的基于用户名/密码的身份验证的支持。InMemoryUserDetailsManager 通过实现 UserDetailsManager 接口来提供 UserDetails 的管理。当 Spring Security 配置为进行 accept a username and password 身份验证时,会使用基于 UserDetails 的身份验证。

Spring Security’s InMemoryUserDetailsManager implements UserDetailsService to provide support for username/password based authentication that is stored in memory. InMemoryUserDetailsManager provides management of UserDetails by implementing the UserDetailsManager interface. UserDetails-based authentication is used by Spring Security when it is configured to servlet-authentication-unpwd-input for authentication.

在以下示例中,我们使用 Spring Boot CLIpassword 的密码值进行编码,并获取 {bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW 的编码密码:

In the following sample, we use Spring Boot CLI to encode a password value of password and get the encoded password of {bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW:

InMemoryUserDetailsManager Java Configuration
  • Java

  • XML

  • Kotlin

@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)
}

前面的示例以安全格式存储密码,但在入门体验方面还有很多需要改进的地方。

The preceding samples store the passwords in a secure format but leave a lot to be desired in terms of a getting started experience.

在以下示例中,我们使用 User.withDefaultPasswordEncoder 来确保存储在内存中的密码受到保护。但是,它无法防止通过反编译源代码获取密码。因此,User.withDefaultPasswordEncoder 仅应用于 “getting started”,而不是为生产而设计的。

In the following sample, we use User.withDefaultPasswordEncoder to ensure that the password stored in memory is protected. However, it does not protect against obtaining the password by decompiling the source code. For this reason, User.withDefaultPasswordEncoder should only be used for “getting started” and is not intended for production.

InMemoryUserDetailsManager with User.withDefaultPasswordEncoder
  • Java

  • Kotlin

@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} 为密码添加前缀,以指示 no encoding should be used

There is no simple way to use User.withDefaultPasswordEncoder with XML-based configuration. For demos or just getting started, you can choose to prefix the password with {noop} to indicate no encoding should be used:

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