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 小时前
图解 MongoDB 26|片键设计:决定集群命运的一个决定
后端·mongodb·agent
Avan_菜菜2 小时前
使用 Docker + rclone 自建 WebDAV
后端·agent·claude
小bo波4 小时前
Java Swing 图形用户界面实验 —— 从算术练习到游戏开发的完整实践
java·课程设计·gui·游戏开发·扫雷·swing
阳光是sunny4 小时前
别再被 worktree 绕晕了!AI 编程时代你必须掌握的 Git 隔离神器
前端·人工智能·后端
万少5 小时前
万少的博客 - 技术分享与解决方案
前端·javascript·后端
咖啡八杯5 小时前
GoF设计模式——备忘录模式
java·后端·spring·设计模式
苍何6 小时前
腾讯再放大招,企微 Agent 大圆开启内测
后端
ethantan6 小时前
一篇讲解AI Agent 组成:像人一样思考的智能体
人工智能·后端·程序员
Cosolar8 小时前
vLLM 生产级部署完全指南
人工智能·后端·架构
IT_陈寒8 小时前
垃圾回收器选错了,我的Java服务内存炸了
前端·人工智能·后端