Spring Security认证与授权的原理(源码分析,超详细)

本文深入解析SpringSecurity的安全访问控制机制,涵盖认证流程、授权流程及其实现原理。从SecurityFilterChain的创建到UsernamePasswordAuthenticationFilter的角色,再到AccessDecisionManager的决策过程,全面解读SpringSecurity如何保障Web应用的安全。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概念:

Spring Security所解决的问题就是安全访问控制,而安全访问控制功能其实就是所有进入系统的请求进行拦截,校验每一个请求是否能够访问它所期望的资源,可以通过Filter或AOP等技术来实现,Spring Security对web资源的保护是靠Filter来实现的。

当初始化Spring Security时,会创建一个名为SpringSecurityFilterChain的servlet过滤器,类型是org.springframework.security.web.FilterChainProxy(有doFilter方法),它实现了javax.servlet.Filter,因此外部请求的类都会经过此类。如图:


实际上,看源代码我们知道FilterChainProxy是一个代理,真正起作用的是FilterChainProxySecurityFilterChain所包含的各个Filter,同时 这些Filter作为BeanSpring管理,它们是Spring Security核心,各有各的职责,但他们并不直接处理用户的,也不直接处理用户的授权,而是把它们交给了认证管理器(AuthenticationManager)和决策管理器(AccessDecisionManager)进行处理,下图是FilterChainProxy相关类的UML图示(直接网上找图)。

不知道UML图的小伙伴们,可以去学一波这个姿势。

Spring Security功能的实现主要是由一系列过滤器链相互配合完成。

(1)SecurityContextPersistenceFilter:这个Filter是整个拦截过程的入口和出口(也就是第一个和最后- 一个拦截器) , 会在请求开始时从配置好的SecurityContextRepository中获取SecurityContext ,然后把它设置给SecurityContextHolder.在请求完成后将SecurityContextHolder持有的SecurityContext再保存到配置好的SecurityContextRepository ,同时清除securityContextHolder所持有的SecurityContext ; .

(2)UsernamePasswordAuthenticationFilter:用于处理来自表单提交的认证。该表单必须提供对应的用户名和密码,其内部还有登录成功或失败后进行处理的AuthenticationSuccessHandler和AuthenticationFailureHandler ,这些都可以根据需求做相关改变;

(3)FilteSecurityInterceptor:是用于保护web资源的,使用AccessDecisionManager对当前用户进行授权访问,前面已经详细介绍过了;

(4)ExceptionTranslationFilter:ExceptionTranslationFilter能够捕获来自FilterChain 所有的异常,并进行处理。但是它只会处理两类异常:ExceptionTranslationFilter能够捕获来自FilterChain 所有的异常,并进行处理。但是它只会处理两类异常:
AuthenticationException和AccessDeniedException ,其它的异常它会继续抛出。


二、认证流程:

(1)用户提交用户名和密码被UsernamePasswordAuthenticationFilter获取到,然后请求的信息被封装为Authentication的实现类UsernamePasswordAuthenticationToken对象。我们来看一下这个源码:UsernamePasswordAuthenticationFilter类的attemptAuthentication方法。

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

	//设置Authentication
	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);
		String password = obtainPassword(request);

		if (username == null) {
			username = "";
		}

		if (password == null) {
			password = "";
		}

		username = username.trim();
        //创建Authentication
		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
				username, password);

		//设置主机地址和sessionId
		setDetails(request, authRequest);
        //通过这个方法去找到A
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值