✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉
🍎个人主页:Leo的博客
💞当前专栏: Java从入门到精通
✨特色专栏: MySQL学习
🥭本文内容:SpringSecurity6 | 默认登录页
🖥️个人小站 :个人博客,欢迎大家访问
📚个人知识库: Leo知识库,欢迎大家访问
学习参考 :
- 讲师:孙帅老师
- 课程:孙哥说SpringSecurity6
✨✨ 粉丝福利订阅✨✨
Leo哥收集了一些关于面试以及其他学习资源,这里分享给大家,各位卷王快收下吧!!!
目录
1.前言
大家好,我是Leo哥🫣🫣🫣,前面我们学习了有关SpringSecurity在SpringBoot项目中是如何给我进行自动的添加鉴权功能,简单复习了一下SpirngBoot的自动配置。接下来我们就接着学习SpringSecurity相关知识点。这一节我们将要学习SpringSecurity中默认的登录页面是如何实现的。好了,话不多说让我们开始吧😎😎😎。
2.涉及过滤器
在在SpringSecurity6核心过滤器中,我们有介绍到当SpringBoot项目启动后,SpringSecurity一共有15个过滤器默认自启动。那么我们请求发出到渲染出默认登录页面这个过程又设计到几个过滤器呢,接下来我们简单介绍一下。
- 首先是
UsernamePasswordAuthenticationFilter
,他主要根据用户名和密码进行认证的。 - 然后就是
DefaultLoginPageGeneratingFilter
,它主要负责默认登录页面的生成。 ExceptionTranslationFilter
,他主要负责SpringSecurity处理认证过程中发生的异常。- 最后就是
AuthorizationFilter
,主要是处理用户的访问认证处理,只有当访问认证通过了,该请求才会被通过。
3.登录页面渲染流程
我们要想知道一个请求是如何被SpringSecurity中一步一步拦截,并生成默认的登录页面的话,我们就必须知道当我们的请求经过SpringSecurity中如何被过滤器拦截,就要知道他的细节。下面我通过一张图来带大家了解,一个请求发出后,在SpringSecurity内部是如何运作的。
页面渲染力流程:
- 访问地址 http://localhost:8500/hello,会经过过个过滤器进行过滤拦截。
- 当请求到达AuthorizationFilter时,系统会检查是否该请求是否进行了认证,如何未认证,则会将该请求拦截下来,并抛出
AccessDenieException
异常。 - 抛出的
AccessDenieException
异常会被ExceptionTranslationFilter破获并启动身份验证,在这个Filter中会调用LoginUrlAuthenticationEntrypoint的commence()方法,并要求重定向到/login页面中去。 - 重定向到/login页面,也就是客户端发送的/loginq请求。
- /login请求会被过滤器
DefaultLoginPageGeneratingFilter
进行拦截,并在过滤器中返回默认的登录页面。
4.重定向登录页
那么上面流程是这么说的,流程图是这么画的,如何验证我们的猜想呢,下面就跟着Leo哥视角,去写一个测试,通过源码追踪的方式去验证我们的猜想。
首先添加一个访问测试接口:
@GetMapping("/test")publicStringtest(){return"Hello SpringSecurity6";}
未登录时访问接口,会 重定向到登录页,流程图如下说示:
流程图说明:
- 一个用户向其未被授权的资源(
/test
)发出一个未经认证的请求。 - 请求进入
SecurityFilterChain
开始执行过滤器,在AuthorizationFilter
中校验不通过,抛出一个AccessDeniedException
。 ExceptionTranslationFilter
捕获到异常,调用LoginUrlAuthenticationEntryPoint
重定向到/login
。- 重定向的
/login
发起请求进入过滤器 /login
会被DefaultLoginPageGeneratingFilter
处理,直接响应写出默认登录页。
4.1 抛出 AccessDeniedException
访问上述接口地址,在SpringSecurity6核心过滤器中,有介绍请求最开始是到达
FilterChainProxy
,由它来调用
SecurityFilterChain
中的过滤器,
/test
是没有经过认证的,依次通过下述所有过滤器。
在通过最后一个过滤器
AuthorizationFilter
中,对当前请求做最后的权限校验,如果没有权限,则会抛出
AccessDeniedException
:
首先
AuthorizationFilter
会取出当前用户认证信息,因为当前请求未认证,用户为
AnonymousAuthenticationFilter
创建的匿名用户:
接着使用
AuthorizationManager
授权管理器对当前认证信息检查,因为是匿名用户,所以判定当前请求无权访问,抛出
AccessDeniedException
:
4.2 异常处理
抛出的
AccessDeniedException
异常会被
ExceptionTranslationFilter
捕获:
ExceptionTranslationFilter
根据异常类型进行相应处理:
接着调用
handleAccessDeniedException
:
接着调用
sendStartAuthentication
缓存请求,并调用
AuthenticationEntryPoint
生成认证入口:
4.3 重定向
接着调用到
LoginUrlAuthenticationEntryPoint
的commence进行重定向或者转发:
4.4 生成默认登录页面
在经过
DefaultLoginPageGeneratingFilter
时,进行默认登录页处理,在该过滤器中,维护了很多参数:
// 登录页地址,默认/loginprivateString loginPageUrl;// 登出成功页地址,默认/login?logoutprivateString logoutSuccessUrl;// 登录错误页地址,默认/login?errorprivateString failureUrl;// 是否开启表单登录privateboolean formLoginEnabled;// 是否开启oauth2登录privateboolean oauth2LoginEnabled;// 是否开启saml2登录privateboolean saml2LoginEnabled;// 认证请求地址,默认/loginprivateString authenticationUrl;// 用户名参数,默认usernameprivateString usernameParameter;// 密码参数,默认passwordprivateString passwordParameter;
重定向的
GET /login
请求则会进入生成登录页逻辑,调用
response
直接输出一个页面,并
return
不再执行后续操作:
那么这个LoginPageHtml是啥呢,其实大家到这里已经可以猜到了,没错就是我们的默认登录页面的HTML,被拼接成了String字符串,最后通过response写出。
我们可以点进去generateLoginPageHtml()这个方法中去查看。
没错,就是我们熟悉的HTML,然后通过StringBuilder拼接然后返回。
最后,我们默认的登录页面就在前端浏览器进行了展示。
5.参考文献
6.总结
以上便是本文的全部内容,本人才疏学浅,文章有什么错误的地方,欢迎大佬们批评指正!我是Leo,一个在互联网行业的小白,立志成为更好的自己。
如果你想了解更多关于Leo,可以关注公众号-程序员Leo,后面文章会首先同步至公众号。
版权归原作者 LeoToJavaer 所有, 如有侵权,请联系我们删除。