mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-30 00:32:14 +00:00
find -name "*.adoc" | xargs -I{file} awk -v file={file} '/\[\[/ { gsub("\[|\]", ""); id=$0; gsub("./docs/modules/ROOT/pages/", "", file); gsub("\[|\]", ""); id=$0;getline;text=$0; sub("^=+ ","", text); print file > "build/ids/"id".id"; print text > "build/ids/"id".text" }' {file} find docs/modules -name "*.adoc"|while read adoc_file_to_replace; do echo "Replacing $adoc_file_to_replace" for id_file in build/ids/*.id; do id=$(basename $id_file | sed 's/\.id$//') xref_page=$(cat $id_file) if [[ "$adoc_file_to_replace" -ef "./docs/modules/ROOT/pages/$xref_page" ]] then echo " - Skipping same page refid $id " else sed -i -E "s%<<$id(|,([^,>]+))>>%xref:${xref_page}#${id}[\2]%g" $adoc_file_to_replace fi done done
133 lines
4.6 KiB
Plaintext
133 lines
4.6 KiB
Plaintext
[[servlet-authentication-inmemory]]
|
|
= In-Memory Authentication
|
|
|
|
Spring Security's `InMemoryUserDetailsManager` implements xref:servlet/authentication/unpwd/user-details-service.adoc#servlet-authentication-userdetailsservice[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 xref:servlet/authentication/unpwd/index.adoc#servlet-authentication-unpwd-input[accept a username/password] for authentication.
|
|
|
|
In this sample we use xref:overview/features/authentication/password-storage.adoc#authentication-password-storage-boot-cli[Spring Boot CLI] to encode the password of `password` and get the encoded password of `+{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW+`.
|
|
|
|
.InMemoryUserDetailsManager Java Configuration
|
|
====
|
|
.Java
|
|
[source,java,role="primary",attrs="-attributes"]
|
|
----
|
|
@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
|
|
[source,xml,role="secondary",attrs="-attributes"]
|
|
----
|
|
<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
|
|
[source,kotlin,role="secondary",attrs="-attributes"]
|
|
----
|
|
@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 xref:overview/features/authentication/password-storage.adoc#authentication-password-storage-dep-getting-started[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
|
|
[source,java,role="primary"]
|
|
----
|
|
@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
|
|
[source,kotlin,role="secondary"]
|
|
----
|
|
@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 xref:overview/features/authentication/password-storage.adoc#authentication-password-storage-dpe-format[no encoding should be used].
|
|
|
|
.<user-service> `+{noop}+` XML Configuration
|
|
====
|
|
[source,xml,attrs="-attributes"]
|
|
----
|
|
<user-service>
|
|
<user name="user"
|
|
password="{noop}password"
|
|
authorities="ROLE_USER" />
|
|
<user name="admin"
|
|
password="{noop}password"
|
|
authorities="ROLE_USER,ROLE_ADMIN" />
|
|
</user-service>
|
|
----
|
|
====
|