SpringSecurity中文文档(UsernamePassword Authentication)

Username/Password Authentication

验证用户的最常见方法之一是验证用户名和密码。SpringSecurity 为使用用户名和密码进行身份验证提供了全面的支持。

您可以使用以下方法配置用户名和密码身份验证:

Simple Username/Password Example

java 复制代码
@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);
	}

}

前面的配置自动在 SecurityFilterChain 中注册了一个内存中的 UserDetailsService,将 DaoAuthenticationProvider 注册到默认的 AuthenticationManager,并启用了表单登录和 HTTP 基本认证。

要了解更多关于用户名/密码身份验证的信息,请考虑以下用例:

Publish an AuthenticationManager bean

一个相当常见的需求是发布一个 AuthenticationManager bean,以允许进行自定义认证,例如在 @Service 或 Spring MVC @Controller 中。例如,您可能希望通过 REST API 认证用户,而不是使用表单登录。

您可以使用以下配置为自定义身份验证方案发布这样的 AuthenticationManager:

Publish AuthenticationManager bean for Custom Authentication

java 复制代码
@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();
	}

}

有了前面的配置,您可以创建一个@RestController,它使用 AuthenticationManager,如下所示:

Create a @RestController for Authentication

java 复制代码
@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) {
	}

}

在本例中,如果需要,您有责任将经过身份验证的用户保存在 SecurityContextRepository 中。例如,如果使用 HttpSession 在请求之间保持 SecurityContext,则可以使用 HttpSessionSecurityContextRepository。

Customize the AuthenticationManager

通常,Spring Security 内部构建一个由 DaoAuthenticationProvider 组成的 AuthenticationManager,用于用户名/密码认证。在某些情况下,可能仍然需要自定义 Spring Security 使用的 AuthenticationManager 实例。例如,您可能需要简单地禁用缓存用户的凭据擦除。

推荐的方法是简单地发布您自己的 AuthenticationManagerbean,SpringSecurity 将使用它。您可以使用以下配置发布 AuthenticationManager:

Publish AuthenticationManager bean for Spring Security

java 复制代码
@Configuration
@EnableWebSecurity
public class SecurityConfig {

	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		http
			.authorizeHttpRequests((authorize) -> authorize
				.requestMatchers("/login").permitAll()
				.anyRequest().authenticated()
			)
			.httpBasic(Customizer.withDefaults())
			.formLogin(Customizer.withDefaults());

		return http.build();
	}

	@Bean
	public AuthenticationManager authenticationManager(
			UserDetailsService userDetailsService,
			PasswordEncoder passwordEncoder) {
		DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
		authenticationProvider.setUserDetailsService(userDetailsService);
		authenticationProvider.setPasswordEncoder(passwordEncoder);

		ProviderManager providerManager = new ProviderManager(authenticationProvider);
		providerManager.setEraseCredentialsAfterAuthentication(false);

		return providerManager;
	}

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

}

或者,您可以利用这样一个事实,即用于构建 Spring Security 的全局 AuthenticationManager 的 AuthenticationManagerBuilder 是作为 bean 发布的。可以按以下方式配置生成器:

Configure global AuthenticationManagerBuilder

java 复制代码
@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);
	}

}
相关推荐
职略1 小时前
负载均衡类型和算法解析
java·运维·分布式·算法·负载均衡
A22741 小时前
LeetCode 196, 73, 105
java·算法·leetcode
容若只如初见2 小时前
项目实战--Spring Boot + Minio文件切片上传下载
java·spring boot·后端
阿里巴巴P8资深技术专家2 小时前
Java常用算法&集合扩容机制分析
java·数据结构·算法
weixin_440401693 小时前
分布式锁——基于Redis分布式锁
java·数据库·spring boot·redis·分布式
码农爱java3 小时前
Spring Boot 中的监视器是什么?有什么作用?
java·spring boot·后端·面试·monitor·监视器
zengson_g3 小时前
当需要对大量数据进行排序操作时,怎样优化内存使用和性能?
java·数据库·算法·排序算法
血战灬狂龙3 小时前
pom.xml文件加载后没有变成maven图标
xml·java·maven
Apifox.4 小时前
什么是 HTTP POST 请求?初学者指南与示范
后端·http·学习方法·web
无名指的等待7124 小时前
SpringBoot实现图片添加水印(完整)
java·spring boot·后端