新版Spring Security6.2案例 - Authentication用户名密码

这篇具有很好参考价值的文章主要介绍了新版Spring Security6.2案例 - Authentication用户名密码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:

前面有翻译了新版Spring Security6.2架构,包括总体架构,Authentication和Authorization,感兴趣可以直接点链接,这篇翻译官网给出的关于Authentication的Username/Password这页。

首先呢,官网就直接给出了基于用户名和密码的认证的代码,可以说是spring security的一个入门小案例,表单登录,输入用户名密码,和内存中的用户名密码匹配,如果匹配了就会成功登录。

Username/Password Authentication

验证用户的最常用方法之一是验证用户名和密码。Spring Security为使用用户名和密码进行身份验证提供了全面的支持。可以通过以下方式配置用户名密码认证

@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 基本身份验证。

官网这边也列举了很多例子,我这边也都附上了超链接,因为前面代码是表单登录的,所以优先把超链接第一点,"我想了解表单登录如何工作"这节翻译了。

要了解更多关于usernamepassword身份验证的信息,请考虑以下用例:

  • 我想了解表单登录如何工作
  • 我想了解HTTP基本身份验证如何工作
  • 我想了解DaoAuthenticationProvider如何工作
  • 我想在内存中管理用户
  • 我想管理数据库中的用户
  • 我想在LDAP中管理用户
  • 我想发布一个用于自定义身份验证的AuthenticationManager bean
  • 我想自定义全局AuthenticationManager

表单登录的原理

Spring Security支持通过HTML表单提供用户名和密码。首先,我们看看如何将用户重定向到登录表单

spring security6.2,SpringSecurity,spring,架构,数据库,spring boot

上图基于 SecurityFilterChain 流程图。 

  1. 首先,用户向未授权的资源 (/private) 发出未经身份验证的请求。
  2. Spring Security 的 AuthorizationFilter 通过抛出 AccessDeniedException 来指示未经身份验证的请求被拒绝。
  3. 由于用户未经过身份验证,因此 ExceptionTranslationFilter 将启动“启动身份验证”,并使用配置的 AuthenticationEntryPoint 将重定向发送到登录页。在大多数情况下,AuthenticationEntryPoint 是 LoginUrlAuthenticationEntryPoint 的实例。
  4. 浏览器请求重定向到的登录页面。
  5. 应用程序中的某些内容必须呈现在登录页面。

当提交用户名和密码时,UsernamePasswordAuthenticationFilter对用户名和密码进行认证。UsernamePasswordAuthenticationFilter扩展了AbstractAuthenticationProcessingFilter,因此下面的图看起来应该非常相似。

spring security6.2,SpringSecurity,spring,架构,数据库,spring boot

该图建立在SecurityFilterChain图的基础上。

1.当用户提交其用户名和密码时,UsernamePasswordAuthenticationFilter 通过从 HttpServletRequest 实例中提取用户名和密码来创建 UsernamePasswordAuthenticationToken,UsernamePasswordAuthenticationToken是一种身份验证类型。

2.接下来,将UsernamePasswordAuthenticationToken传递到要进行身份验证的AuthenticationManager实例中。AuthenticationManager的细节取决于用户信息的存储方式。

3.如果身份验证失败,则定义为”失败“,并做如下:

        (1).清除SecurityContextHolder。

        (2).调用 RememberMeServices.loginFail。如果未配置“记住我”,则为空操作。请参阅 Javadoc 中的 RememberMeServices 接口。

        (3).调用AuthenticationFailureHandler。请参阅Javadoc中的AuthenticationFailureHandler类

4.如果身份验证成功,则显定义为”成功“,并做如下:

        (1).SessionAuthenticationStrategy收到新登录的通知。请参阅Javadoc中的SessionAuthenticationStrategy接口。

        (2).身份验证设置在securitycontexholder上。请参阅Javadoc中的SecurityContextPersistenceFilter类。

        (3).RememberMeServices。调用loginSuccess。如果记得我没有配置,这是一个no-op。请参阅Javadoc中的memormeservices接口。

        (4).ApplicationEventPublisher发布一个InteractiveAuthenticationSuccessEvent事件。

        (5).调用AuthenticationSuccessHandler。通常,这是一个SimpleUrlAuthenticationSuccessHandler,当我们重定向到登录页面时,它会重定向到由ExceptionTranslationFilter保存的请求。

默认情况下,Spring Security 表单登录处于启用状态。但是,一旦提供了任何基于 servlet 的配置,就必须显式提供基于表单的登录。以下示例显示了一个最小的显式 Java 配置:

public SecurityFilterChain filterChain(HttpSecurity http) {
	http
		.formLogin(withDefaults());
	// ...
}

在前面的配置中,Spring Security 呈现默认登录页面。大多数生产应用程序都需要自定义登录表单。

以下配置演示了如何提供自定义登录表单。

ublic SecurityFilterChain filterChain(HttpSecurity http) {
	http
		.formLogin(form -> form
			.loginPage("/login")
			.permitAll()
		);
	// ...
}

在 Spring Security 配置中指定登录页面时,用户负责呈现页面。以下 Thymeleaf 模板生成符合 /login 登录页的 HTML 登录表单。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
	<head>
		<title>Please Log In</title>
	</head>
	<body>
		<h1>Please Log In</h1>
		<div th:if="${param.error}">
			Invalid username and password.</div>
		<div th:if="${param.logout}">
			You have been logged out.</div>
		<form th:action="@{/login}" method="post">
			<div>
			<input type="text" name="username" placeholder="Username"/>
			</div>
			<div>
			<input type="password" name="password" placeholder="Password"/>
			</div>
			<input type="submit" value="Log in" />
		</form>
	</body>
</html>

关于默认 HTML 表单,有几个关键点:

  • 表单应执行 post 到 /login。
  • 该表单需要包含一个 CSRF 令牌,该令牌由 Thymeleaf 自动包含。
  • 表单应在名为 username 的参数中指定用户名。
  • 表单应在名为 password 的参数中指定密码。
  • 如果找到名为 error 的 HTTP 参数,则表示用户未能提供有效的用户名或密码。
  • 如果找到名为 logout 的 HTTP 参数,则表示用户已成功注销。

许多用户只需要自定义登录页面即可。但是,如果需要,您可以使用其他配置自定义前面显示的所有内容。

如果您使用 Spring MVC,则需要一个将 GET /login 映射到我们创建的登录模板的控制器。以下示例显示了一个最小的 LoginController:

@Controller
class LoginController {
	@GetMapping("/login")
	String login() {
		return "login";
	}
}

最后在官网Username/Password这页中,还有描写关于自定义身份的authentication bean和全局authenticationManger,也就是上面超链接最后2点,先翻译出来,再后续博客中接着讲,本文可以着重看前面的表单登录即可

发布一个AuthenticationManager bean

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

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

}

有了上述配置,您就可以创建一个使用AuthenticationManager的@RestController,如下所示:

@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) {
	}

}

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

自定义 AuthenticationManager

通常,Spring Security 在内部构建一个 AuthenticationManager,该管理器由 DaoAuthenticationProvider 组成,用于用户名/密码身份验证。在某些情况下,可能仍需要自定义 Spring Security 使用的 AuthenticationManager 实例。例如,您可能需要简单地为缓存用户禁用凭据擦除。您可以使用以下配置发布 AuthenticationManager:

@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 发布的事实。您可以按如下方式配置构建器:

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

}

参考文献:

《spring boot官网》文章来源地址https://www.toymoban.com/news/detail-830926.html

到了这里,关于新版Spring Security6.2案例 - Authentication用户名密码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Security6入门及自定义登录

    Spring Security已经更新到了6.x,很多常见的方法都废弃了,并且将在未来的 Spring Security7 中移除,主要总结几点变化。 本文代码环境jdk版本17、boot版本3.1.2、security6.1.2 准确来说,Spring Security 是在 5.7.0-M2 这个版本中将 WebSecurityConfigurerAdapter 过期的,过期的原因是因为官方想要鼓

    2024年02月14日
    浏览(34)
  • Gateway中Spring Security6统一处理CORS

    使用了 gateway 微服务作为整体的网关,并且整合了 Spring Security6 ;还有一个system微服务,作为被请求的资源,当浏览器向 gateway 发送请求,请求 system 资源时,遇到 CORS 问题。 于是我在 system 对应的 controller 上加了 @CrossOrigin ,无效;配置 WebMvcConfigurer ,也无效。 后来发现,

    2024年02月20日
    浏览(33)
  • 系列三、Spring Security中自定义用户名/密码

    1.1.1、配置文件中配置 1.1.2、定义基于内存的用户 1.1.3、基于UserDetailService接口定义用户 概述:         Spring Security支持多种数据源,例如内存、数据库、LDAP等,这些不同来源的数据被共同封装成了UserDetailService接口,换句话说任何实现了UserDetailService接口的对象都可以作为

    2024年01月19日
    浏览(32)
  • Spring Security详细讲解(JWT+SpringSecurity登入案例)

    1.SpringSecurity SpringSecurity 是一个功能强大且高度可定制的身份验证和访问控制框架 。它是保护基于 Spring 的应用程序的事实上的标准。 SpringSecurity 是一个致力于为 Java 应用程序提供身份验证和授权的框架 。像所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以如何轻

    2024年02月02日
    浏览(46)
  • Spring Security Oauth2.1 最新版 1.1.0 整合 gateway 完成授权认证(拥抱 springboot 3.1)

    目录 背景 demo地址 版本 Spring Boot 3.1 Spring Authorization Server 1.1.0 基础 spring security OAuth2 模块构成 授权方式 认证方式 集成过程 官方demo 代码集成 依赖 授权服务AuthorizationServerConfig配置 重要组件 测试 查看授权服务配置 访问授权服务 授权 回调 获取 access_token 获取用户信息 个性

    2024年02月08日
    浏览(61)
  • Spring Security Oauth2.1 最新版 1.1.0 整合 (基于 springboot 3.1.0)gateway 完成授权认证

    目录 背景 demo地址 版本 Spring Boot 3.1 Spring Authorization Server 1.1.0 基础 spring security OAuth2 模块构成 授权方式 认证方式 集成过程 官方demo 代码集成 依赖 授权服务AuthorizationServerConfig配置 重要组件 测试 查看授权服务配置 访问授权服务 授权 回调 获取 access_token 获取用户信息 个性

    2024年02月11日
    浏览(48)
  • Spring Security 6.x 系列【1】基础篇之概述及入门案例

    有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.0.4 本系列Spring Security 版本 6.0.2 源码地址:https://gitee.com/pearl-organization/study-spring-security-demo 本系列基于最新 Spring Boot 3.0 + Spring Security 6.0 版本,由浅入深,从实战到源码分析,详细讲解各种 Spring Security 的使用

    2024年02月06日
    浏览(57)
  • Spring Security 6.x 系列【28】授权服务器篇之Spring Authorization Server 1.0 入门案例

    有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.0.4 本系列Spring Security 版本 6.0.2 本系列Spring Authorization Server 版本 1.0.2 源码地址:https://gitee.com/pearl-organization/study-spring-security-demo 在前几篇文档中,我们学习了 OAuth 2.0 协议,并使用 spring-security-oauth2-client 完成

    2024年02月12日
    浏览(39)
  • 在提交文件到gitee远程仓库时报用户名密码错误 fatal: Authentication failed for ‘https://gitee.com/xxx/xxx.git 解决方案来啦 亲测有效

    在提交文件到gitee远程仓库时,突然出现一个弹框输入用户名 密码 很懵逼 输入了结果是错误的 D:文件名git push -u origin \\\"master\\\" remote: [session-fa417d86] Akiko: Incorrect username or password (access token) fatal: Authentication failed for \\\'https://gitee.com/xxx/文件名.git/\\\'      此刻如果再提交一遍 还是会

    2024年02月16日
    浏览(59)
  • “error“:{“root_cause“:[{“type“:“security_exception“,“reason“:“missing authentication token for REST

    出现此401错误 {\\\"error\\\":{\\\"root_cause\\\":[{\\\"type\\\":\\\"security_exception\\\",\\\"reason\\\":\\\"missing authentication token for REST request [/idx]\\\",\\\"header\\\":{\\\"WWW-Authenticate\\\":\\\"Basic realm=\\\"security\\\" charset=\\\"UTF-8\\\"\\\"}}],\\\"type\\\":\\\"security_exception\\\",\\\"reason\\\":\\\"missing authentication token for REST request [/idx]\\\",\\\"header\\\":{\\\"WWW-Authenticate\\\":\\\"Basic realm=\\\"security\\\"

    2024年02月05日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包