in-memory.adoc 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. [[servlet-authentication-inmemory]]
  2. = In-Memory Authentication
  3. Spring Security's `InMemoryUserDetailsManager` implements xref:servlet/authentication/passwords/user-details-service.adoc#servlet-authentication-userdetailsservice[UserDetailsService] to provide support for username/password based authentication that is stored in memory.
  4. `InMemoryUserDetailsManager` provides management of `UserDetails` by implementing the `UserDetailsManager` interface.
  5. `UserDetails`-based authentication is used by Spring Security when it is configured to <<servlet-authentication-unpwd-input,accept a username and password>> for authentication.
  6. In the following sample, we use xref:features/authentication/password-storage.adoc#authentication-password-storage-boot-cli[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+`:
  7. .InMemoryUserDetailsManager Java Configuration
  8. [tabs]
  9. ======
  10. Java::
  11. +
  12. [source,java,role="primary",attrs="-attributes"]
  13. ----
  14. @Bean
  15. public UserDetailsService users() {
  16. UserDetails user = User.builder()
  17. .username("user")
  18. .password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
  19. .roles("USER")
  20. .build();
  21. UserDetails admin = User.builder()
  22. .username("admin")
  23. .password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
  24. .roles("USER", "ADMIN")
  25. .build();
  26. return new InMemoryUserDetailsManager(user, admin);
  27. }
  28. ----
  29. XML::
  30. +
  31. [source,xml,role="secondary",attrs="-attributes"]
  32. ----
  33. <user-service>
  34. <user name="user"
  35. password="{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW"
  36. authorities="ROLE_USER" />
  37. <user name="admin"
  38. password="{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW"
  39. authorities="ROLE_USER,ROLE_ADMIN" />
  40. </user-service>
  41. ----
  42. Kotlin::
  43. +
  44. [source,kotlin,role="secondary",attrs="-attributes"]
  45. ----
  46. @Bean
  47. fun users(): UserDetailsService {
  48. val user = User.builder()
  49. .username("user")
  50. .password("{bcrypt}$2a$10\$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
  51. .roles("USER")
  52. .build()
  53. val admin = User.builder()
  54. .username("admin")
  55. .password("{bcrypt}$2a$10\$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
  56. .roles("USER", "ADMIN")
  57. .build()
  58. return InMemoryUserDetailsManager(user, admin)
  59. }
  60. ----
  61. ======
  62. The preceding samples store the passwords in a secure format but leave a lot to be desired in terms of a getting started experience.
  63. In the following sample, we use xref:features/authentication/password-storage.adoc#authentication-password-storage-dep-getting-started[User.withDefaultPasswordEncoder] to ensure that the password stored in memory is protected.
  64. However, it does not protect against obtaining the password by decompiling the source code.
  65. For this reason, `User.withDefaultPasswordEncoder` should only be used for "`getting started`" and is not intended for production.
  66. .InMemoryUserDetailsManager with User.withDefaultPasswordEncoder
  67. [tabs]
  68. ======
  69. Java::
  70. +
  71. [source,java,role="primary"]
  72. ----
  73. @Bean
  74. public UserDetailsService users() {
  75. // The builder will ensure the passwords are encoded before saving in memory
  76. UserBuilder users = User.withDefaultPasswordEncoder();
  77. UserDetails user = users
  78. .username("user")
  79. .password("password")
  80. .roles("USER")
  81. .build();
  82. UserDetails admin = users
  83. .username("admin")
  84. .password("password")
  85. .roles("USER", "ADMIN")
  86. .build();
  87. return new InMemoryUserDetailsManager(user, admin);
  88. }
  89. ----
  90. Kotlin::
  91. +
  92. [source,kotlin,role="secondary"]
  93. ----
  94. @Bean
  95. fun users(): UserDetailsService {
  96. // The builder will ensure the passwords are encoded before saving in memory
  97. val users = User.withDefaultPasswordEncoder()
  98. val user = users
  99. .username("user")
  100. .password("password")
  101. .roles("USER")
  102. .build()
  103. val admin = users
  104. .username("admin")
  105. .password("password")
  106. .roles("USER", "ADMIN")
  107. .build()
  108. return InMemoryUserDetailsManager(user, admin)
  109. }
  110. ----
  111. ======
  112. There is no simple way to use `User.withDefaultPasswordEncoder` with XML-based configuration.
  113. For demos or just getting started, you can choose to prefix the password with `+{noop}+` to indicate xref:features/authentication/password-storage.adoc#authentication-password-storage-dpe-format[no encoding should be used]:
  114. .<user-service> `+{noop}+` XML Configuration
  115. [source,xml,attrs="-attributes"]
  116. ----
  117. <user-service>
  118. <user name="user"
  119. password="{noop}password"
  120. authorities="ROLE_USER" />
  121. <user name="admin"
  122. password="{noop}password"
  123. authorities="ROLE_USER,ROLE_ADMIN" />
  124. </user-service>
  125. ----