spring security 认证流程

1.认证流程

在这里插入图片描述
(1)用户发起登录请求后,首先进入 UsernamePasswordAuthenticationFilter(AbstractAuthenticationProcessingFilter)

AbstractAuthenticationProcessingFilter中doFilter方法
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {

		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		
		// 1.判断请求是否是login和post,UsernamePasswordAuthenticationFilter的构造方法
		if (!requiresAuthentication(request, response)) {
			chain.doFilter(request, response);

			return;
		}

		if (logger.isDebugEnabled()) {
			logger.debug("Request is to process authentication");
		}

		Authentication authResult;

		try {
			//2.调用子类UsernamePasswordAuthenticationFilter的attemptAuthentication方法,
			//在attemptAuthentication方法中创建了一个authenticated为false(即未授权)的UsernamePasswordAuthenticationToken,并传递给AuthenticationManager().authenticate()这个方法进行认证,
			//认证成功后,返回一个authenticated=true的UsernamePasswordAuthenticationToken对象
			authResult = attemptAuthentication(request, response);
			if (authResult == null) {
				// return immediately as subclass has indicated that it hasn't completed
				// authentication
				return;
			}
			sessionStrategy.onAuthentication(authResult, request, response);
		}
		catch (InternalAuthenticationServiceException failed) {
			logger.error(
					"An internal error occurred while trying to authenticate the user.",
					failed);
			// 3.认证失败后通过调用AuthenticationFailureHandler 的onAuthenticationFailure 接口进行失败处理,可以通过继承AuthenticationFailureHandler 进行自定义失败逻辑
			unsuccessfulAuthentication(request, response, failed);

			return;
		}
		catch (AuthenticationException failed) {
			// Authentication failed
			// 4.认证失败后通过调用AuthenticationFailureHandler 的onAuthenticationFailure 接口进行失败处理,可以通过继承AuthenticationFailureHandler 进行自定义失败逻辑
			unsuccessfulAuthentication(request, response, failed);

			return;
		}

		// Authentication success
		if (continueChainBeforeSuccessfulAuthentication) {
			chain.doFilter(request, response);
		}
		// 5.认证成功后调用AuthenticationSuccessHandler 的onAuthenticationSuccess 接口进行成功处理,也可以通过继承AuthenticationSuccessHandler 自行实现成功处理逻辑
		successfulAuthentication(request, response, chain, authResult);
	}
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();
		// 根据用户名和密码生成 未认证的UsernamePasswordAuthenticationToken 
		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
				username, password);

		setDetails(request, authRequest);
		//将生成未认证的UsernamePasswordAuthenticationToken 交给AuthenticationManager 处理
		return this.getAuthenticationManager().authenticate(authRequest);
	}

AuthenticationManager 本身不包含认证逻辑,核心用来管理所有的AuthenticationProvider,通过交给合适的AuthenticationProvider来实现认证

(2)跳转到ProviderManager ,该类是AuthenticationManager 的实现类
在这里插入图片描述
不同的登录逻辑他的认证方式是不一样的,
springsecurity 支持多种认证逻辑,每一种认证逻辑的认证方式其实就是一种AuthenticationProvider。通过getProviders方法获取所有的AuthenticationProvider,通过supports来判断是否支持当前认证逻辑。
当选择好一个合适的AuthenticationProvider后,通过provider.authenticate()来让AuthenticationProvider 进行认证。
(3)传统表单登录的AuthenticationProvider主要是由AbstractUserDetailsAuthenticationProvider 来进行处理的,我们来看下它的authenticate()

首先调用retrieveUser来获取到数据库用户信息

在这里插入图片描述
当我们成功的读取UserDetails之后,下面开始对其进行认证

在这里插入图片描述
在上图中,我们可以看到认证校验分为 前校验、附加校验和后校验,如果任何一个校验出错,就会抛出相应的异常。所有校验都通过后,调用 createSuccessAuthentication() 返回认证信息。
在这里插入图片描述

createSuccessAuthentication方法中,重新new了一个UsernamePasswordAuthenticationToken,并将authorities传进去,设置authenticated为true
(4)至此认证信息被传递回UsernamePasswordAuthenticationFilter 中,在 UsernamePasswordAuthenticationFilter 的父类 AbstractAuthenticationProcessingFilter 的 doFilter() 中,会根据认证的成功或者失败调用相应的 handler:
在这里插入图片描述

二、多个请求共享session用户信息

spring security通过session保存用户认真信息
下面将 Spring Security 的认证流程补充完整,如下图:

在这里插入图片描述
在上一节认证成功的 successfulAuthentication()方法中,有一行语句:

SecurityContextHolder.getContext().setAuthentication(authResult);

三、获取用户信息

通过调用 SecurityContextHolder.getContext().getAuthentication() 就能够取得认证信息

@GetMapping("/me")
@ResponseBody
public Object me() {
    return SecurityContextHolder.getContext().getAuthentication();
}

上面的写法有点啰嗦,我们可以简写成下面这种, Spring MVC 会自动帮我们从 Spring Security 中注入:

@GetMapping("/me")
@ResponseBody
public Object me(Authentication authentication) {
    return authentication;
}

如果你仅想获取 UserDetails 对象,也是可以的,写法如下:

@GetMapping("/me")
@ResponseBody
public Object me(@AuthenticationPrincipal UserDetails userDetails) {
    return userDetails;
}

转载https://jitwxs.blog.csdn.net/article/details/84703690

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值