SpringSecurity过滤器UsernamePasswordAuthenticationFilter

简介

UsernamePasswordAuthenticationFilter是AbstractAuthenticationProcessingFilter针对使用用户名和密码进行身份认证而定制化的一个过滤器。其添加是在调用http.formLogin()时作用,默认的登录请求pattern为"/login",并且为POST请求。当我们登录的时候,也就是匹配到loginProcessingUrl,这个过滤器就会委托认证管理器authenticationManager来验证登录

在这里插入图片描述

1、AbstractAuthenticationProcessingFilter

登陆流程入口是AbstractAuthenticationProcessingFilter的doFilter方法

public abstract class AbstractAuthenticationProcessingFilter extends GenericFilterBean
		implements ApplicationEventPublisherAware, MessageSourceAware {

	protected ApplicationEventPublisher eventPublisher;
	protected AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
	private AuthenticationManager authenticationManager;
	protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
	private RememberMeServices rememberMeServices = new NullRememberMeServices();

	private RequestMatcher requiresAuthenticationRequestMatcher;

	private boolean continueChainBeforeSuccessfulAuthentication = false;

	private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy();

	private boolean allowSessionCreation = true;

	private AuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
	private AuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
	
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
        //判断当前路径是否是指定的登陆路径,如果不是,那么跳过此过滤器
        //UsernamePasswordAuthenticationFilter默认登陆路径是/login,post接口
		if (!requiresAuthentication(request, response)) {
			chain.doFilter(request, response);
			return;
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Request is to process authentication");
		}
		Authentication authResult;

		try {
		    //对请求进行权限验证,这是一个抽象方法
		    //其实现 在UsernamePasswordAuthenticationFilter中
			authResult = attemptAuthentication(request, response);
			if (authResult == null) {
				return;
			}
			sessionStrategy.onAuthentication(authResult, request, response);
		}
		catch (InternalAuthenticationServiceException failed) {
		    //身份验证失败的默认行为。			
			unsuccessfulAuthentication(request, response, failed);
			return;
		}
		catch (AuthenticationException failed) {
		    //身份验证失败的默认行为。
			unsuccessfulAuthentication(request, response, failed);
			return;
		}

		// Authentication success
		if (continueChainBeforeSuccessfulAuthentication) {
			chain.doFilter(request, response);
		}
       //身份验证成功的默认行为。	
		successfulAuthentication(request, response, chain, authResult);
	}
}

AbstractAuthenticationProcessingFilter其实没做什么,只是对请求路径进行了过滤,判断是否是登陆路径。对请求认证的代码在其子类UsernamePasswordAuthenticationFilter中

2、UsernamePasswordAuthenticationFilter
public class UsernamePasswordAuthenticationFilter extends
		AbstractAuthenticationProcessingFilter {
	
	public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
	public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";

	private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
	private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
	private boolean postOnly = true;

    //设置默认登陆路径
    public UsernamePasswordAuthenticationFilter() {
		super(new AntPathRequestMatcher("/login", "POST"));
	}

	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
		
		//接口类型判断
		if (postOnly && !request.getMethod().equals("POST")) {
			throw new AuthenticationServiceException(
					"Authentication method not supported: " + request.getMethod());
		}

		String username = obtainUsername(request);//获取用户名,默认通过request.getParamete方式获取
		String password = obtainPassword(request);//获取密码,默认通过request.getParamete方式获取

		if (username == null) {username = "";}
		if (password == null) {password = "";}
		username = username.trim();

		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);

		// 允许子类设置“details”属性
		setDetails(request, authRequest);
        //调用AuthenticationManager的authenticate进行认证和授权
		return this.getAuthenticationManager().authenticate(authRequest);
	}
}
3、自定义用户名和密码登陆逻辑
public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {




    //登陆失败返回结果自定义
    public void unsuccessfulAuthentication(HttpServletRequest request,
                                           HttpServletResponse response, AuthenticationException failed)
            throws IOException, ServletException {

        SecurityContextHolder.clearContext();

        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        String msg = "";
        if (failed instanceof LockedException) {
            msg = "账户被锁定,请联系管理员!";
        } else if (failed instanceof CredentialsExpiredException) {
            msg = "密码过期,请联系管理员!";
        } else if (failed instanceof AccountExpiredException) {
            msg = "账户过期,请联系管理员!";
        } else if (failed instanceof DisabledException) {
            msg = "账户被禁用,请联系管理员!";
        } else if (failed instanceof BadCredentialsException) {
            msg = "用户名或者密码输入错误,请重新输入!";
        }else if (failed instanceof AuthenticationServiceException) {
            msg = failed.getMessage();
        }
        out.write(new ObjectMapper().writeValueAsString(JsonResultHelper.JsonResultFail(msg)));
        out.flush();
        out.close();


    }

    //登陆成功返回结果自定义
    public void successfulAuthentication(HttpServletRequest request,
                                         HttpServletResponse response, FilterChain chain, Authentication authResult)
            throws IOException, ServletException {

        SecurityContextHolder.getContext().setAuthentication(authResult);

        // Fire event
        if (this.eventPublisher != null) {
            eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(
                    authResult, this.getClass()));
        }

        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write(new ObjectMapper().writeValueAsString(JsonResultHelper.JsonResultSuccess(authResult)));
        out.flush();
        out.close();


    }

}

MyUsernamePasswordAuthenticationFilter的注册

@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        ExceptionTranslationFilter w;
        return NoOpPasswordEncoder.getInstance();
    }

    @Bean
    public MyUserDetailsService myUserDetailsService(){
        return new MyUserDetailsService();
    }


    @Bean
    public MyUsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter() throws Exception {
        MyUsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter = new MyUsernamePasswordAuthenticationFilter();
        myUsernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager());
        return myUsernamePasswordAuthenticationFilter;
    }


    @Override
    protected void configure(HttpSecurity auth) throws Exception               
        auth.addFilterAt(myUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        auth.csrf().disable()
                .authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .httpBasic();
    }
}
Spring Security是一个用于保护Java应用程序的框架,它提供了一系列过滤器来处理安全相关的任务。在Spring Security中,过滤器被组织成一个过滤器链(Filter Chain),它根据配置的顺序依次执行。以下是一些常用的Spring Security过滤器及其功能: 1. SecurityContextPersistenceFilter:用于在请求处理期间存储和检索SecurityContext,即当前用户的安全上下文。 2. LogoutFilter:处理用户注销请求,并清除当前用户的认证信息。 3. UsernamePasswordAuthenticationFilter:用于处理基于用户名和密码的认证请求。 4. ConcurrentSessionFilter:用于处理并发会话控制,限制同一用户的同时登录数。 5. BasicAuthenticationFilter:用于处理基于HTTP基本身份验证的认证请求。 6. RequestCacheAwareFilter:用于缓存请求,以便在重定向后重新发送请求。 7. SecurityContextHolderAwareRequestFilter:用于包装请求,使其能够识别特定的安全上下文。 8. AnonymousAuthenticationFilter:用于在请求上下文中添加匿名用户的认证信息。 9. SessionManagementFilter:用于处理会话管理,例如过期检查、并发控制等。 10. ExceptionTranslationFilter:用于捕获并处理异常,将其转换为合适的响应。 11. FilterSecurityInterceptor:用于实施访问控制,检查用户是否具有访问资源的权限。 这些过滤器可以根据具体的安全需求进行配置和组合,以提供所需的安全功能。通过指定不同的过滤器顺序、添加自定义过滤器或替换默认过滤器,您可以灵活地定制Spring Security过滤器链。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值