`

spring-security(二十一)核心Filter-UsernamePasswordAuthenticationFilter

阅读更多
一、UsernamePasswordAuthenticationFilter功能和属性
到目前为止,我们已经探讨了三个主要的filter,当采用默认配置时spring security会自动给我们追加这三个filter,现在我们的filter中还差一个处理用户认证的filter,下面我们就主要讨论下最常用的认证filter-UsernamePasswordAuthenticationFilter。

1.重要属性
  • AuthenticationManager 认证用,默认情况下是ProviderManager
  • RememberMeServices 如果启用remember功能,spring会给我们注入一个TokenBasedRememberMeServices,如果不启用remember功能,采用默认的NullRememberMeServices。
  • RequestMatcher 用来判断当前HttpServletRequest请求是否需要用当前过滤器进行处理,默认匹配URL是/login,httpMethod是POST的请求
  • SessionAuthenticationStrategy 认证成功后会调用这个类的onAuthentication,来做一些session的处理
  • AuthenticationSuccessHandler 认证成功后处理器,默认采用SavedRequestAwareAuthenticationSuccessHandler,会将用户重定向到引起认证处理的原始请求,继续之前的操作
  • AuthenticationFailureHandler 认证失败后的处理器,默认将用户重定向到defaultFailureUrl,如 /login?error

2.处理逻辑
2.1 当请求进入到这个过滤器时,首先利用requiresAuthenticationRequestMatcher属性对request进行匹配,如果匹配成功就继续执行filter里面的逻辑,如果不匹配直接执行下一个filter。
2.2 如果2.1匹配成功开始尝试认证处理
2.2.1 首先从request中获取到username和password(参数名称可定制化),组装成一个UsernamePasswordAuthenticationToken
2.2.2 如果有额外信息需要保存调用authenticationDetailsSource.buildDetails构建详情追加的Token中
2.2.3 之后调用authenticationManager.authenticate方法进行认证,认证成功后这个方法会给我们返回一个组装好的Authentication对象
2.2.3.1认证成功后执行逻辑
    a. 调用sessionStrategy.onAuthentication方法,对session进行一些处理,这个功能比较重要,下面会再详细讨论
    b. 将组装好的Authentication存放到SecurityContextHolder中
    c. 调用rememberMeServices的loginSuccess方法,如果配置了remember功能这边会将我们的用户名和密码序列化后存入到cookie中,对应的key是remember-me
    d.接着调用successHandler的onAuthenticationSuccess方法,默认继续执行引起认证处理的原始请求
2.2.3.2 认证失败后的执行逻辑
   a.清除SecurityContextHolder中的认证信息
   b.执行rememberMeServices.loginFail方法将cookie中key是remember-me的值设置成null
3.关于SessionAuthenticationStrategy
3.1 默认配置下,spring security在servelet3.1+环境下会为我们构建ChangeSessionIdAuthenticationStrategy(低版本的servlet下构建SessionFixationProtectionStrategy)来处理session fixation攻击,如果启用了csrf,spring会再给我们启用一个CsrfAuthenticationStrategy,如果启用了并发session控制,spring会再给我注入ConcurrentSessionControlAuthenticationStrategy和RegisterSessionAuthenticationStrategy,所以在启用csrf和currency session功能后最终会有四个SessionAuthenticationStrategy,之后spring会将这四个SessionAuthenticationStrategy组合成一个CompositeSessionAuthenticationStrategy赋值到这个认证filter中。
最终的结果按顺序排列如下:
  • ConcurrentSessionControlAuthenticationStrategy 当发现同一个用户达到最大并发登陆数时,将这个用户最后活动时间最早的session设置成过期,用户对应的session信息从SessionRegistry中获取。
  • ChangeSessionIdAuthenticationStrategy 用户认证成功后修改sessionId,防止session fixation攻击
  • RegisterSessionAuthenticationStrategy 用户认证成功后将用户对应的session信息存放到SessionRegistry中,供ConcurrentSessionControlAuthenticationStrategy使用
  • CsrfAuthenticationStrategy,用户认证成功后清除原来的csrf token,再重新生成一个csrf token,存入CsrfTokenRepository中并设置到request中,供CsrfFilter使用,后续处理的csrf Token都有CsrfFilter来管理


其中ConcurrentSessionControlAuthenticationStrategy和RegisterSessionAuthenticationStrategy 对应的SessionRegistry是同一个实例,默认的实现是SessionRegistryImpl。这个类里面主要是两个hashmap,一个是用户与sessionId的对应关系,一个存储session与SessionInformation的对应关系
/** <principal:Object,SessionIdSet> */
private final ConcurrentMap<Object, Set<String>> principals = new ConcurrentHashMap<Object, Set<String>>();
/** <sessionId:Object,SessionInformation> */
private final Map<String, SessionInformation> sessionIds = new ConcurrentHashMap<String, SessionInformation>();

RegisterSessionAuthenticationStrategy会调用这个类的registerNewSession方法,向这个用户对应的sessionIds中追加一个当前sessionId和SessionInformation的对应记录。
ConcurrentSessionControlAuthenticationStrategy在认证成功后获取当前用户对应的所有sessionId,从而判断size是否达到最大限制进行并发登录控制。
二、在spring boot环境下,采用Java config机制这个filter是如何追加到servlet中对我们的请求进行拦截的呢。
在前面的章节(spring-security(十六)Filter配置原理)中,我们知道spring 安全相关的Filter是在WebSecurity的build方法中调用HttpSecurity的build来将追加到HttpSecurity中filter列表排好序后构建成SecurityFilterChain,再把所有的SecurityFilterChain追加到FilterChainProxy中,最后通过DelegatingFilterProxy注册到ServletContext中的,下面我们主要来看下这个类是如何追加到HttpSecuriy的filter列表中的。
1.从我们的配置入口WebSecurityConfigurerAdapter类开始,采用默认配置时,在这个类的configure(HttpSecurity http)方法中(我们大多数的定制化处理都是重写这个方法来实现的),会调用http.formLogin()方法
public FormLoginConfigurer<HttpSecurity> formLogin() throws Exception {
    return getOrApply(new FormLoginConfigurer<HttpSecurity>());
}

在这个方法中创建了一个实现了SecurityConfigurer接口的配置类FormLoginConfigurer,通过调用getOrApply方法最终追加到HttpSecurity的configurers属性中,通过这个配置类我们也可以设置自定义的登录页面、设置认证处理的请求路径、设置登录成功后的跳转地址(不设置的话就是跳转到引起认证请求的地址)、设置登录失败后的默认跳转地址等。
2.FormLoginConfigurer类的构造函数
public FormLoginConfigurer() {
    super(new UsernamePasswordAuthenticationFilter(), null);
    usernameParameter("username");
    passwordParameter("password");
}

在构造函数中为我们创建了一个UsernamePasswordAuthenticationFilter,并设置默认的用户名和密码对应的参数名称是username、password。
3. 看下这个filter对应的属性是如何设置的
WebSecurity在构建HttpSecurity时,会调用HttpSecurity的build方法,这个方法会先执行HttpSecurity的configure()方法,就是依次调用configurers属性中各个SecurityConfigurer的configure方法
private void configure() throws Exception {
  Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
  for (SecurityConfigurer<O, B> configurer : configurers) {
     configurer.configure((B) this);
  }
}

下面来看下FormLoginConfigurer的configure方法,具体的逻辑在其父类AbstractAuthenticationFilterConfigurer中
@Override
public void configure(B http) throws Exception {
	PortMapper portMapper = http.getSharedObject(PortMapper.class);
	if (portMapper != null) {
		authenticationEntryPoint.setPortMapper(portMapper);
	}
	authFilter.setAuthenticationManager(http
			.getSharedObject(AuthenticationManager.class));
	authFilter.setAuthenticationSuccessHandler(successHandler);
	authFilter.setAuthenticationFailureHandler(failureHandler);
	if (authenticationDetailsSource != null) {
	authFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
	}
	SessionAuthenticationStrategy sessionAuthenticationStrategy = http
			.getSharedObject(SessionAuthenticationStrategy.class);
	if (sessionAuthenticationStrategy != null) {
authFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);
	}
	RememberMeServices rememberMeServices = http
			.getSharedObject(RememberMeServices.class);
	if (rememberMeServices != null) {
		authFilter.setRememberMeServices(rememberMeServices);
	}
	F filter = postProcess(authFilter);
	http.addFilter(filter);
}

很明显在这个configure方法中,为filter设置了AuthenticationManager、AuthenticationSuccessHandler、AuthenticationFailureHandler、SessionAuthenticationStrategy、RememberMeServices等我们在前面看到的所需的属性。除了SessionAuthenticationStrategy,其余属性的设置都比较简单,SessionAuthenticationStrategy的设置逻辑需参考SessionManagementConfigurer的init和configure方法以及CsrfConfigurer的configure方法,这里不再具体展开。
在上面方法的最后将我们配置好的filter通过http.addFilter追加到了HttpSecurity的filter列表中,这样就可以和其他的过滤器一样对我们的请求进行过滤了。

以上就是UsernamePasswordAuthenticationFilter的主要内容,这个filter也是我们最常用的用户名和密码认证方式的主要处理类,后面我们还会陆续讲解其他的认证方式以及对应的filter。
分享到:
评论

相关推荐

    spring-boot-security

    3. **过滤器链(Filter Chain)**:Spring Security的核心组件之一是过滤器链,它由多个过滤器组成,如`UsernamePasswordAuthenticationFilter`和`HttpSessionAuthenticationStrategy`等。这些过滤器负责处理HTTP...

    Spring-Security_java_

    **Spring Security 的核心组件** 1. **Filter Chain**: Spring Security 使用一系列过滤器(Filter)来拦截 HTTP 请求,执行身份验证和授权检查。每个过滤器都有特定的任务,如 `...

    spring-security-4.0 jar包

    在Spring Security中,所有的安全性操作都是通过Filter Chain来实现的。这些过滤器如`DelegatingFilterProxy`、`SecurityContextPersistenceFilter`、`UsernamePasswordAuthenticationFilter`等,按照配置的顺序...

    spring-security简单demo

    3. **过滤器链(Filter Chain)**:Spring Security 的核心是基于Servlet Filter的过滤器链。这个链上的每个过滤器都有特定的任务,比如`UsernamePasswordAuthenticationFilter`处理登录请求,`...

    spring-security 案例

    - **过滤器链(Filter Chain)**:Spring Security的核心组件,处理HTTP请求并进行安全拦截。 2. **配置Spring Security** - **WebSecurityConfigurerAdapter**:Spring Security的配置类,通过继承该类并覆盖其...

    spring-Security简单例子

    - **自定义登录页面**: 可以创建一个自定义的登录表单,提交的请求会被Spring Security的`UsernamePasswordAuthenticationFilter`处理。 - **登录失败处理器**: 自定义`AuthenticationFailureHandler`来处理登录...

    spring-security-one完整版.rar

    - **Filter Chain**:Spring Security基于一系列过滤器(如`DelegatingFilterProxy`、`ChannelProcessingFilter`、`UsernamePasswordAuthenticationFilter`等)来拦截HTTP请求,执行安全逻辑。 - **Role-Based ...

    spring-security3.1源码

    3. **Filter安全链**:Spring Security 的Web安全功能主要通过一系列过滤器实现,这些过滤器构成了安全链。其中关键的过滤器有`DelegatingFilterProxy`、`ChannelProcessingFilter`、`...

    spring-security第三回

    3. **过滤器链(Filter Chain)**:Spring Security的核心是过滤器链,它由多个安全相关的过滤器组成,这些过滤器按照特定顺序执行,处理HTTP请求。主要的过滤器包括`DelegatingFilterProxy`、`...

    spring-security3入门教程

    - **请求处理**:当用户尝试访问受保护的资源时,Spring Security 的 Filter Security Interceptor 检测请求并触发认证过程。 - **登录**:用户提交登录信息后,UsernamePasswordAuthenticationFilter 处理这些...

    spring-security 3.02 jar包及源码.rar

    3. **过滤器链(Filter Chain)**:Spring Security的核心是其过滤器链,它拦截HTTP请求并执行相应的安全逻辑。例如,UsernamePasswordAuthenticationFilter负责处理登录请求,RememberMeAuthenticationFilter处理...

    初识 Spring Security - v1.1.pdf

    - **Spring Security 定义好的核心Filter**:包括一系列内置过滤器,如`UsernamePasswordAuthenticationFilter`等。 ##### 10. **退出登录** - **概念**:提供了退出登录的功能,清除用户的认证状态。 ##### 11. ...

    spring security 3.1.3 源码含sample源码

    Spring Security是Spring框架的一个核心组件,专注于提供身份验证和授权服务,用于构建安全的Java Web应用程序。3.1.3版本是它的一个较早版本,但依然包含了许多关键的安全特性。这个压缩包提供了Spring Security ...

    springboot-security.zip

    SpringBoot以其简化Spring应用的初始搭建以及开发过程而受到广大开发者喜爱,而SpringSecurity则是一个强大的安全框架,它提供了全面的安全管理解决方案,包括身份验证、授权等核心功能。 SpringSecurity的核心概念...

    SpringSecurity笔记,编程不良人笔记

    - **Filter Chain**: SpringSecurity通过一系列过滤器实现其安全功能,这些过滤器构成了Filter Chain。每个过滤器负责特定的安全任务,如认证、授权等。 - **Authentication**: 表示用户的身份信息,包括用户名、...

    spring-security_examples:Spring 安全示例

    关键的过滤器包括 `DelegatingFilterProxy`(指向 Spring Security 的 FilterChainProxy)、`SecurityContextPersistenceFilter`(在请求之间保持安全上下文)、`UsernamePasswordAuthenticationFilter`(处理登录...

    spring security 源文件

    - **Filter Chain**: Spring Security 的核心是过滤器链,它处理HTTP请求,执行安全相关的操作,如认证和授权。 - **AuthenticationManager**: 负责用户身份验证,它可以根据配置的认证提供者(如...

    spring security 参考手册中文版

    核心 - spring-security-core.jar 25 远程处理 - spring-security-remoting.jar 25 Web - spring-security-web.jar 25 配置 - spring-security-config.jar 26 LDAP - spring-security-ldap.jar 26 ACL - spring-...

    Spring_Security_多页面登录配置教程

    `AuthenticationProcessingFilter`是Spring Security中用于处理用户登录请求的核心组件之一。它负责接收用户提交的登录信息并进行验证。为了支持多页面登录,我们需要为每个登录页面配置一个`...

    SpringSecurity实现的权限管理(含包)

    3. **过滤器链(Filter Chain)**:SpringSecurity的核心组件之一是过滤器链,它处理HTTP请求并应用安全策略。默认的过滤器链包括了如UsernamePasswordAuthenticationFilter(处理表单登录)、...

Global site tag (gtag.js) - Google Analytics