servlet-authentication-passwords-storage-in-memory.md 4.3 KB
Newer Older
茶陵後's avatar
茶陵後 已提交
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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
# In-Memory Authentication

Spring Security’s `InMemoryUserDetailsManager` implements [UserDetailsService](user-details-service.html#servlet-authentication-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 [accept a username/password](index.html#servlet-authentication-unpwd-input) for authentication.

In this sample we use [Spring Boot CLI](../../../features/authentication/password-storage.html#authentication-password-storage-boot-cli) to encode the password of `password` and get the encoded password of `{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW`.

Example 1. InMemoryUserDetailsManager Java Configuration

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);
}
```

XML

```
<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>
```

Kotlin

```
@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 samples above store the passwords in a secure format, but leave a lot to be desired in terms of getting started experience.

In the sample below we leverage [User.withDefaultPasswordEncoder](../../../features/authentication/password-storage.html#authentication-password-storage-dep-getting-started) 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.

Example 2. InMemoryUserDetailsManager with User.withDefaultPasswordEncoder

Java

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

Kotlin

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

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](../../../features/authentication/password-storage.html#authentication-password-storage-dpe-format).

Example 3. \<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>
```

[Password Storage](storage.html)[JDBC](jdbc.html)