in-memory.adoc 4.6 KB

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