java 登录编程_SpringSecurity 默认表单登录页展示流程源码

本篇主要讲解 SpringSecurity提供的默认表单登录页 它是如何展示的的流程,

涉及

1.FilterSecurityInterceptor,

2.ExceptionTranslationFilter ,

3.DefaultLoginPageGeneratingFilter 过滤器,

并且简单介绍了 AccessDecisionManager 投票机制

1.准备工作(体验SpringSecurity默认表单认证)

1.1 创建SpringSecurity项目

先通过IDEA 创建一个SpringBoot项目 并且依赖SpringSecurity,Web依赖

8ebbc365ec81e4bfebd8426f985dc2ea.png

此时pom.xml会自动添加

f0282ca5270677cf921c376c2a697c8a.png

1.2 提供一个接口

841ffbe8d97489ac9cc8456da80b1a55.png

1.3 启动项目

直接访问 提供的接口

89b8f467f9fc2ac2834b42d43808857f.png

会发现浏览器被直接重定向到了 /login 并且显示如下默认的表单登录页

ce105df189febf01d0075d2c3c9ec483.png

06d329884dc198e6fee0ba9eab28c360.png

1.4 登录

在启动项目的时候 控制台会打印一个 seuciryt password : xxx

Using generated security password: f520875f-ea2b-4b5d-9b0c-f30c0c17b90b

直接登录

用户名:user 密码 :f520875f-ea2b-4b5d-9b0c-f30c0c17b90b

登录成功并且浏览器又会重定向到刚刚访问的接口

c3403cf176a387b2309f499a7f45fa08.png

2.springSecurityFilterchain 过滤器链

如果你看过我另一篇关于SpringSecurity初始化源码的博客,那么你一定知道当SpringSecurity项目启动完成后会初始化一个 springSecurityFilterchain 它内部 additionalFilters属性初始化了很多Filter 如下所有的请求都会经过这一系列的过滤器 Spring Security就是通过这些过滤器 来进行认证授权等

a665ccc72495809af969541477e5dc88.png

3.FilterSecurityInterceptor (它会判断这次请求能否通过)

FilterSecurityInterceptor是过滤器链中最后一个过滤器,主要用于判断请求能否通过,内部通过AccessDecisionManager 进行投票判断

当我们未登录访问

2e955a6a85075b4268bc7a95cb60be1d.png

请求会被 FilterSecurityInterceptor 拦截

8dc584c0884d52b8209741caa246a63f.png

重点看invoke方法

577a6db97868f6c3fa3b7cd62c245468.png

源码中有这样一句,其实就是判断当前用户是否能够访问指定的接口,可以则执行 fi.getChain().doFilter 调用访问的接口否则 内部会抛出异常

InterceptorStatusToken token = super.beforeInvocation(fi);

beforeInvocation 方法内部是通过 accessDecisionManager 去做决定的Spring Security已经内置了几个基于投票的AccessDecisionManager包括(AffirmativeBased ,ConsensusBased ,UnanimousBased)当然如果需要你也可以实现自己的AccessDecisionManager

使用这种方式,一系列的AccessDecisionVoter将会被AccessDecisionManager用来对Authentication是否有权访问受保护对象进行投票,然后再根据投票结果来决定是否要抛出AccessDeniedException

this.accessDecisionManager.decide(authenticated, object, attributes);

AffirmativeBased的 decide的实现如下

81122fea2df88282310c41770136abf9.png

AffirmativeBased的逻辑是这样的:

(1)只要有AccessDecisionVoter的投票为ACCESS_GRANTED则同意用户进行访问;

(2)如果全部弃权也表示通过;

(3)如果没有一个人投赞成票,但是有人投反对票,则将抛出AccessDeniedException。

当我们第一次访问的时候

33cd9094edfbe18364e318b62b456154.png

返回 result = -1 会抛出 AccessDeniedException 拒绝访问异常

4.ExceptionTranslationFilter (捕获AccessDeniedException异常)

该过滤器它会接收到FilterSecurityInterceptor抛出的 AccessDeniedException异常)并且进行捕获,然后发送重定向到/login请求

源码如下:

12b6ca9eefadb49d1e09f950a9af5783.png

3e0efa76b4c268d1b036bd308011d2cd.png

当获取异常后 调用

handleSpringSecurityException(request, response, chain, ase);

handleSpringSecurityException 源码如下:

7c1e604a352024aab1954a037647a005.png

6e408013a22b03a3f53a202558f019f3.png

先判断获取的异常是否是AccessDeniedException 再判断是否是匿名用户,如果是则调用 sendStartAuthentication 重定向到登录页面

重定向登录页面之前会保存当前访问的路径,这就是为什么我们访问 /hello接口后 再登录成功后又会跳转到 /hello接口,因为在重定向到/login接口前 这里进行了保存 requestCache.saveRequest(request, response);

013561a9db4bbee77554bfbdb56dc49d.png

authenticationEntryPoint.commence(request, response, reason);方法内部

调用LoginUrlAuthenticationEntryPoint 的 commence方法

224f661449490e4d91f812f7ed66b159.png

LoginUrlAuthenticationEntryPoint 的commence方法内部有 构造重定向URL的方法

85a9a8fd01bb7ffad60dc0c057a00323.png

最终会获取到需要重定向的URL /login

65eb3a086dfeb25e0b0f7667dd918e68.png

然后sendRedirect既会重定向到/login请求

9d41830bdf3cdae762da580e96e053ca.png

5.DefaultLoginPageGeneratingFilter (会捕获重定向的/login 请求)

DefaultLoginPageGeneratingFilter是过滤器链中的一个用于捕获/login请求,并且渲染出一个默认表单页面

2c2f4579af551d9f8d0bfe7e1f49c252.png

isLoginUrlRequest 判断请求是否是 loginPageUrl

41b998dfda75482930e02d77216f9144.png

因为我们没有配置所以默认的loginPageUrl=/login

060a240efe398fe658c782cc544d6484.png

验证通过请求路径 能匹配 loginPageUrl

744a5bc40e2b048781c6dbedfaa0c78e.png

generateLoginPageHtml 绘制默认的HTML 页面,到此我们默认的登录页面怎么来的就解释清楚了

34f1926bd9296e1d61214adf1c680ad6.png

fbac6b4a31c69c1ae33471cda6eb0df6.png

ebf5bc74ad6a5471162f3da855e9a9a8.png

029c6b902ad2bb2563b2762411810629.png

至此 SpringSecurity 默认表单登录页展示流程源码部分已经全部讲解完毕,会渲染出下面的页面,但是一定要有网的情况,否则样式可能会变化

06d329884dc198e6fee0ba9eab28c360.png

6.总结

本篇主要讲解 SpringSecurity提供的默认表单登录页 它是如何展示的的流程,包括涉及这一流程中相关的 3个过滤器1.FilterSecurityInterceptor,2.ExceptionTranslationFilter ,3.DefaultLoginPageGeneratingFilter 过滤器,并且简单介绍了一下 AccessDecisionManager 它主要进行投票来判断该用户是否能够访问相应的 资源AccessDecisionManager 投票机制我也没有深究 后续我会详细深入一下再展开

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值