基于SpringSecurity OAuth2实现单点登录——未认证的请求是如何重定向到登录地址的?(SpringSecurity的认证流程)

本文深入剖析了SpringSecurity框架中未认证请求如何被重定向到登录页面的过程。通过FilterChainProxy和FilterSecurityInterceptor等关键组件的分析,揭示了从触发AccessDeniedException异常到调用LoginUrlAuthenticationEntryPoint完成重定向的完整逻辑。

1、《入门示例和流程分析》
2、《未认证的请求是如何重定向到登录地址的》
3、《应用A是如何重定向到授权服务器的授权地址呢?》
4、《授权服务器是如何实现授权的呢?》
5、《登录访问应用A后再访问应用B会发生什么呢?》

1、前言

  在上一篇《入门示例和流程分析》的流程分析过程中,当第一次(未认证的情况下)访问应用A(http://localhost:8082/index)时,会重定向到应用A的登录http://localhost:8082/login地址(Get请求),从浏览器这个视角我们看到的是这样的情况,那么在应用A的服务端又经历了什么呢?我们通过代码进行分析。

2、SpringSecurity过滤器链

  这节分析的问题,其实就是SpringSecurity关于认证过程的逻辑。SpringSecurity实现认证逻辑,就是通过SpringSecurity 过滤器链实现的,我们先了解一下SpringSecurity过滤器链中的核心类FilterChainProxy。

2.1、FilterChainProxy

在这里插入图片描述
  在SpringSecurity中,SpringSecurity 的过滤器并不是直接内嵌到Servlet Filter中的,而是通过FilterChainProxy来统一管理的,即所有的Spring Security Filter的执行,都在FilterChainProxy中进行管理的,所以我们选择从FilterChainProxy类入手进行分析。

  为了实现上述描述的功能,SpringSecurity 过滤器由FilterChainProxy统一管理,然后在在内部定义了一个VirtualFilterChain内部类,用于表示SpringScurity内部的过滤器链,其中doFilter()方法用于执行过滤器链中的过滤器。如下所示:

//FilterChainProxy#VirtualFilterChain,省略了Debug相关信息
@Override
public void doFilter(ServletRequest request, ServletResponse response)
		throws IOException, ServletException {
   
   
	if (currentPosition == size) {
   
   
		// Deactivate path stripping as we exit the security filter chain
		this.firewalledRequest.reset();
		//执行Web中的过滤器
		originalChain.doFilter(request, response);
	}
	else {
   
   //执行SpringSecurity过滤器链中的过滤器
		currentPosition++;
		//additionalFilters中定义了SpringSecurity过滤器链中的所有过滤器
		Filter nextFilter = additionalFilters.get(currentPosition - 1);
		nextFilter.doFilter(request, response, this);
	}
}

  我们通过断点,可以查看additionalFilters变量中的过滤器集合,即SpringSecurity过滤器链中所有过滤器,下面是应用A中的SpringSecurity 过滤器,如下所示:
nextFilter.doFilter

3、FilterSecurityInterceptor过滤器

  通过Debug执行代码,我们发现,在执行完FilterSecurityInterceptor过滤器时,前端页面重定向到了应用A的登录http://localhost:8082/login地址(Get请求)。在执行过滤器FilterSecurityInterceptor过滤器时,发生了什么呢?我们通过Debug方式,进行逐步的分析。

  首先,我们进入FilterSecurityInterceptor过滤器的doFilter()方法,在doFilter()方法中又调用了invoke()方法,而在invoke()方法中,又调用了父类AbstractSecurityInterceptor的beforeInvocation()方法,如下所示:

//FilterSecurityInterceptor.java

public void doFilter(ServletRequest request, ServletResponse response,
		FilterChain chain) throws IOException, ServletException {
   
   
	FilterInvocation fi = new FilterInvocation(request, response, chain);
	invoke(fi);
}
	
public void invoke(FilterInvocation fi) throws IOException, ServletException {
   
   
	if ((fi.getRequest(
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姠惢荇者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值