| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 | 
							- [[servlet-authentication-unpwd]]
 
- = Username/Password Authentication
 
- :page-section-summary-toc: 1
 
- :figures: images/servlet/authentication/unpwd
 
- :icondir: images/icons
 
- One of the most common ways to authenticate a user is by validating a username and password.
 
- Spring Security provides comprehensive support for authenticating with a username and password.
 
- You can configure username and password authentication using the following:
 
- .Simple Username/Password Example
 
- [tabs]
 
- =====
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			.authorizeHttpRequests((authorize) -> authorize
 
- 				.anyRequest().authenticated()
 
- 			)
 
- 			.httpBasic(Customizer.withDefaults())
 
- 			.formLogin(Customizer.withDefaults());
 
- 		return http.build();
 
- 	}
 
- 	@Bean
 
- 	public UserDetailsService userDetailsService() {
 
- 		UserDetails userDetails = User.withDefaultPasswordEncoder()
 
- 			.username("user")
 
- 			.password("password")
 
- 			.roles("USER")
 
- 			.build();
 
- 		return new InMemoryUserDetailsManager(userDetails);
 
- 	}
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<intercept-url pattern="/**" access="authenticated"/>
 
- 	<form-login />
 
- 	<http-basic />
 
- 	<user-service>
 
- 		<user name="user"
 
- 			password="{noop}password"
 
- 			authorities="ROLE_USER" />
 
- 	</user-service>
 
- </http>
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
- 	@Bean
 
- 	fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
- 		http {
 
- 			authorizeHttpRequests {
 
- 				authorize(anyRequest, authenticated)
 
- 			}
 
- 			formLogin { }
 
- 			httpBasic { }
 
- 		}
 
- 		return http.build()
 
- 	}
 
- 	@Bean
 
- 	fun userDetailsService(): UserDetailsService {
 
- 		val user = User.withDefaultPasswordEncoder()
 
- 			.username("user")
 
- 			.password("password")
 
- 			.roles("USER")
 
- 			.build()
 
- 		return InMemoryUserDetailsManager(user)
 
- 	}
 
- }
 
- ----
 
- =====
 
- The preceding configuration automatically registers an xref:servlet/authentication/passwords/in-memory.adoc[in-memory `UserDetailsService`] with the `SecurityFilterChain`, registers the xref:servlet/authentication/passwords/dao-authentication-provider.adoc[`DaoAuthenticationProvider`] with the default xref:servlet/authentication/architecture.adoc#servlet-authentication-authenticationmanager[`AuthenticationManager`], and enables xref:servlet/authentication/passwords/form.adoc[Form Login] and xref:servlet/authentication/passwords/basic.adoc[HTTP Basic] authentication.
 
- To learn more about username/password authentication, consider the following use cases:
 
- * I want to xref:servlet/authentication/passwords/form.adoc[learn how Form Login works]
 
- * I want to xref:servlet/authentication/passwords/basic.adoc[learn how HTTP Basic authentication works]
 
- * I want to xref:servlet/authentication/passwords/dao-authentication-provider.adoc[learn how `DaoAuthenticationProvider` works]
 
- * I want to xref:servlet/authentication/passwords/in-memory.adoc[manage users in memory]
 
- * I want to xref:servlet/authentication/passwords/jdbc.adoc[manage users in a database]
 
- * I want to xref:servlet/authentication/passwords/ldap.adoc#servlet-authentication-ldap-authentication[manage users in LDAP]
 
- * I want to <<publish-authentication-manager-bean,publish an `AuthenticationManager` bean>> for custom authentication
 
- * I want to <<customize-global-authentication-manager,customize the global `AuthenticationManager`>>
 
- [[publish-authentication-manager-bean]]
 
- == Publish an `AuthenticationManager` bean
 
- A fairly common requirement is publishing an `AuthenticationManager` bean to allow for custom authentication, such as in a `@Service` or Spring MVC `@Controller`.
 
- For example, you may want to authenticate users via a REST API instead of using xref:servlet/authentication/passwords/form.adoc[Form Login].
 
- You can publish such an `AuthenticationManager` for custom authentication scenarios using the following configuration:
 
- .Publish `AuthenticationManager` bean for Custom Authentication
 
- [tabs]
 
- =====
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			.authorizeHttpRequests((authorize) -> authorize
 
- 				.requestMatchers("/login").permitAll()
 
- 				.anyRequest().authenticated()
 
- 			);
 
- 		return http.build();
 
- 	}
 
- 	@Bean
 
- 	public AuthenticationManager authenticationManager(
 
- 			UserDetailsService userDetailsService,
 
- 			PasswordEncoder passwordEncoder) {
 
- 		DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
 
- 		authenticationProvider.setUserDetailsService(userDetailsService);
 
- 		authenticationProvider.setPasswordEncoder(passwordEncoder);
 
- 		return new ProviderManager(authenticationProvider);
 
- 	}
 
- 	@Bean
 
- 	public UserDetailsService userDetailsService() {
 
- 		UserDetails userDetails = User.withDefaultPasswordEncoder()
 
- 			.username("user")
 
- 			.password("password")
 
- 			.roles("USER")
 
- 			.build();
 
- 		return new InMemoryUserDetailsManager(userDetails);
 
- 	}
 
- 	@Bean
 
- 	public PasswordEncoder passwordEncoder() {
 
- 		return PasswordEncoderFactories.createDelegatingPasswordEncoder();
 
- 	}
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http>
 
- 	<intercept-url pattern="/login" access="permitAll"/>
 
- 	<intercept-url pattern="/**" access="authenticated"/>
 
- 	<bean id="authenticationManager"
 
- 			class="org.springframework.security.authentication.ProviderManager">
 
- 		<constructor-arg>
 
- 			<bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
 
- 				<property name="userDetailsService" ref="userDetailsService" />
 
- 				<property name="passwordEncoder" ref="passwordEncoder" />
 
- 			</bean>
 
- 		</constructor-arg>
 
- 	</bean>
 
- 	<user-service id="userDetailsService">
 
- 		<user name="user"
 
- 			password="{noop}password"
 
- 			authorities="ROLE_USER" />
 
- 	</user-service>
 
- 	<bean id="passwordEncoder"
 
- 			class="org.springframework.security.crypto.factory.PasswordEncoderFactories" factory-method="createDelegatingPasswordEncoder"/>
 
- </http>
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
- 	@Bean
 
- 	fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
- 		http {
 
- 			authorizeHttpRequests {
 
- 				authorize("/login", permitAll)
 
- 				authorize(anyRequest, authenticated)
 
- 			}
 
- 		}
 
- 		return http.build()
 
- 	}
 
- 	@Bean
 
- 	fun authenticationManager(
 
- 			userDetailsService: UserDetailsService,
 
- 			passwordEncoder: PasswordEncoder): AuthenticationManager {
 
- 		val authenticationProvider = DaoAuthenticationProvider()
 
- 		authenticationProvider.setUserDetailsService(userDetailsService)
 
- 		authenticationProvider.setPasswordEncoder(passwordEncoder)
 
- 		return ProviderManager(authenticationProvider)
 
- 	}
 
- 	@Bean
 
- 	fun userDetailsService(): UserDetailsService {
 
- 		val user = User.withDefaultPasswordEncoder()
 
- 			.username("user")
 
- 			.password("password")
 
- 			.roles("USER")
 
- 			.build()
 
- 		return InMemoryUserDetailsManager(user)
 
- 	}
 
- 	@Bean
 
- 	fun passwordEncoder(): PasswordEncoder {
 
- 		return PasswordEncoderFactories.createDelegatingPasswordEncoder()
 
- 	}
 
- }
 
- ----
 
- =====
 
- With the preceding configuration in place, you can create a `@RestController` that uses the `AuthenticationManager` as follows:
 
- .Create a `@RestController` for Authentication
 
- [tabs]
 
- =====
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @RestController
 
- public class LoginController {
 
- 	private final AuthenticationManager authenticationManager;
 
- 	public LoginController(AuthenticationManager authenticationManager) {
 
- 		this.authenticationManager = authenticationManager;
 
- 	}
 
- 	@PostMapping("/login")
 
- 	public ResponseEntity<Void> login(@RequestBody LoginRequest loginRequest) {
 
- 		Authentication authenticationRequest =
 
- 			UsernamePasswordAuthenticationToken.unauthenticated(loginRequest.username(), loginRequest.password());
 
- 		Authentication authenticationResponse =
 
- 			this.authenticationManager.authenticate(authenticationRequest);
 
- 		// ...
 
- 	}
 
- 	public record LoginRequest(String username, String password) {
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- @RestController
 
- class LoginController(val authenticationManager: AuthenticationManager) {
 
- 	@PostMapping("/login")
 
- 	fun login(@RequestBody loginRequest: LoginRequest): ResponseEntity<Void> {
 
- 		val authenticationRequest =
 
- 			UsernamePasswordAuthenticationToken.unauthenticated(
 
- 				loginRequest.username, loginRequest.password)
 
- 		val authenticationResponse =
 
- 			authenticationManager.authenticate(authenticationRequest)
 
- 		// ...
 
- 	}
 
- 	data class LoginRequest(val username: String, val password: String)
 
- }
 
- ----
 
- =====
 
- [NOTE]
 
- ====
 
- In this example, it is your responsibility to save the authenticated user in the `SecurityContextRepository` if needed.
 
- For example, if using the `HttpSession` to persist the `SecurityContext` between requests, you can use xref:servlet/authentication/persistence.adoc#httpsecuritycontextrepository[`HttpSessionSecurityContextRepository`].
 
- ====
 
- [[customize-global-authentication-manager]]
 
- == Customize the `AuthenticationManager`
 
- Normally, Spring Security builds an `AuthenticationManager` internally composed of a `DaoAuthenticationProvider` for username/password authentication.
 
- In certain cases, it may still be desired to customize the instance of `AuthenticationManager` used by Spring Security.
 
- For example, you may need to simply disable xref:servlet/authentication/architecture.adoc#servlet-authentication-providermanager-erasing-credentials[credential erasure] for cached users.
 
- To do this, you can take advantage of the fact that the `AuthenticationManagerBuilder` used to build Spring Security's global `AuthenticationManager` is published as a bean.
 
- You can configure the builder as follows:
 
- .Configure global `AuthenticationManagerBuilder`
 
- [tabs]
 
- =====
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		// ...
 
- 		return http.build();
 
- 	}
 
- 	@Bean
 
- 	public UserDetailsService userDetailsService() {
 
- 		// Return a UserDetailsService that caches users
 
- 		// ...
 
- 	}
 
- 	@Autowired
 
- 	public void configure(AuthenticationManagerBuilder builder) {
 
- 		builder.eraseCredentials(false);
 
- 	}
 
- }
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
- 	@Bean
 
- 	fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
- 		// ...
 
- 		return http.build()
 
- 	}
 
- 	@Bean
 
- 	fun userDetailsService(): UserDetailsService {
 
- 		// Return a UserDetailsService that caches users
 
- 		// ...
 
- 	}
 
- 	@Autowired
 
- 	fun configure(builder: AuthenticationManagerBuilder) {
 
- 		builder.eraseCredentials(false)
 
- 	}
 
- }
 
- ----
 
- =====
 
- Alternatively, you may configure a local `AuthenticationManager` to override the global one.
 
- .Configure local `AuthenticationManager` for Spring Security
 
- [tabs]
 
- =====
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Configuration
 
- @EnableWebSecurity
 
- public class SecurityConfig {
 
- 	@Bean
 
- 	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 
- 		http
 
- 			.authorizeHttpRequests((authorize) -> authorize
 
- 				.anyRequest().authenticated()
 
- 			)
 
- 			.httpBasic(Customizer.withDefaults())
 
- 			.formLogin(Customizer.withDefaults())
 
- 			.authenticationManager(authenticationManager());
 
- 		return http.build();
 
- 	}
 
- 	private AuthenticationManager authenticationManager() {
 
- 		DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
 
- 		authenticationProvider.setUserDetailsService(userDetailsService());
 
- 		authenticationProvider.setPasswordEncoder(passwordEncoder());
 
- 		ProviderManager providerManager = new ProviderManager(authenticationProvider);
 
- 		providerManager.setEraseCredentialsAfterAuthentication(false);
 
- 		return providerManager;
 
- 	}
 
- 	private UserDetailsService userDetailsService() {
 
- 		UserDetails userDetails = User.withDefaultPasswordEncoder()
 
- 			.username("user")
 
- 			.password("password")
 
- 			.roles("USER")
 
- 			.build();
 
- 		return new InMemoryUserDetailsManager(userDetails);
 
- 	}
 
- 	private PasswordEncoder passwordEncoder() {
 
- 		return PasswordEncoderFactories.createDelegatingPasswordEncoder();
 
- 	}
 
- }
 
- ----
 
- XML::
 
- +
 
- [source,xml,role="secondary"]
 
- ----
 
- <http authentication-manager-ref="authenticationManager">
 
- 	<intercept-url pattern="/**" access="authenticated"/>
 
- 	<form-login />
 
- 	<http-basic />
 
- 	<bean id="authenticationManager"
 
- 			class="org.springframework.security.authentication.ProviderManager">
 
- 		<constructor-arg>
 
- 			<bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
 
- 				<property name="userDetailsService" ref="userDetailsService" />
 
- 				<property name="passwordEncoder" ref="passwordEncoder" />
 
- 			</bean>
 
- 		</constructor-arg>
 
- 	</bean>
 
- 	<user-service id="userDetailsService">
 
- 		<user name="user"
 
- 			password="{noop}password"
 
- 			authorities="ROLE_USER" />
 
- 	</user-service>
 
- 	<bean id="passwordEncoder"
 
- 			class="org.springframework.security.crypto.factory.PasswordEncoderFactories" factory-method="createDelegatingPasswordEncoder"/>
 
- </http>
 
- ----
 
- Kotlin::
 
- +
 
- [source,kotlin,role="secondary"]
 
- ----
 
- import org.springframework.security.config.annotation.web.invoke
 
- @Configuration
 
- @EnableWebSecurity
 
- class SecurityConfig {
 
- 	@Bean
 
- 	fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 
- 		http {
 
- 			authorizeHttpRequests {
 
- 				authorize(anyRequest, authenticated)
 
- 			}
 
- 			formLogin { }
 
- 			httpBasic { }
 
- 			authenticationManager = authenticationManager()
 
- 		}
 
- 		return http.build()
 
- 	}
 
- 	@Bean
 
- 	fun authenticationManager(): AuthenticationManager {
 
- 		val authenticationProvider = DaoAuthenticationProvider()
 
- 		authenticationProvider.setUserDetailsService(userDetailsService())
 
- 		authenticationProvider.setPasswordEncoder(passwordEncoder())
 
- 		val providerManager = ProviderManager(authenticationProvider)
 
- 		providerManager.eraseCredentialsAfterAuthentication = false
 
- 		return providerManager
 
- 	}
 
- 	private fun userDetailsService(): UserDetailsService {
 
- 		val user = User.withDefaultPasswordEncoder()
 
- 			.username("user")
 
- 			.password("password")
 
- 			.roles("USER")
 
- 			.build()
 
- 		return InMemoryUserDetailsManager(user)
 
- 	}
 
- 	private fun passwordEncoder(): PasswordEncoder {
 
- 		return PasswordEncoderFactories.createDelegatingPasswordEncoder()
 
- 	}
 
- }
 
- ----
 
- =====
 
 
  |