SpringSecurity6 | 默认登录页

SpringSecurity6 | 默认登录页

学习参考 :

1.前言

大家好,我是Leo哥🫣🫣🫣,前面我们学习了有关SpringSecurity在SpringBoot项目中是如何给我进行自动的添加鉴权功能,简单复习了一下SpirngBoot的自动配置。接下来我们就接着学习SpringSecurity相关知识点。这一节我们将要学习SpringSecurity中默认的登录页面是如何实现的。好了,话不多说让我们开始吧😎😎😎。

2.涉及过滤器

在在SpringSecurity6核心过滤器中,我们有介绍到当SpringBoot项目启动后,SpringSecurity一共有15个过滤器默认自启动。那么我们请求发出到渲染出默认登录页面这个过程又设计到几个过滤器呢,接下来我们简单介绍一下。

  • 首先是UsernamePasswordAuthenticationFilter,他主要根据用户名和密码进行认证的。
  • 然后就是DefaultLoginPageGeneratingFilter,它主要负责默认登录页面的生成。
  • ExceptionTranslationFilter,他主要负责SpringSecurity处理认证过程中发生的异常。
  • 最后就是AuthorizationFilter,主要是处理用户的访问认证处理,只有当访问认证通过了,该请求才会被通过。

3.登录页面渲染流程

我们要想知道一个请求是如何被SpringSecurity中一步一步拦截,并生成默认的登录页面的话,我们就必须知道当我们的请求经过SpringSecurity中如何被过滤器拦截,就要知道他的细节。下面我通过一张图来带大家了解,一个请求发出后,在SpringSecurity内部是如何运作的。

页面渲染力流程:

  1. 访问地址 http://localhost:8500/hello,会经过过个过滤器进行过滤拦截。
  2. 当请求到达AuthorizationFilter时,系统会检查是否该请求是否进行了认证,如何未认证,则会将该请求拦截下来,并抛出AccessDenieException异常。
  3. 抛出的AccessDenieException异常会被ExceptionTranslationFilter破获并启动身份验证,在这个Filter中会调用LoginUrlAuthenticationEntrypoint的commence()方法,并要求重定向到/login页面中去。
  4. 重定向到/login页面,也就是客户端发送的/loginq请求。
  5. /login请求会被过滤器DefaultLoginPageGeneratingFilter进行拦截,并在过滤器中返回默认的登录页面。

4.重定向登录页

那么上面流程是这么说的,流程图是这么画的,如何验证我们的猜想呢,下面就跟着Leo哥视角,去写一个测试,通过源码追踪的方式去验证我们的猜想。

首先添加一个访问测试接口:

typescript 复制代码
@GetMapping("/test")
public String test() {
    return "Hello SpringSecurity6";
}

未登录时访问接口,会 重定向到登录页,流程图如下说示:

流程图说明:

  1. 一个用户向其未被授权的资源(/test)发出一个未经认证的请求。
  2. 请求进入SecurityFilterChain开始执行过滤器,在AuthorizationFilter中校验不通过,抛出一个AccessDeniedException
  3. ExceptionTranslationFilter捕获到异常,调用LoginUrlAuthenticationEntryPoint重定向到/login
  4. 重定向的/login发起请求进入过滤器
  5. /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时,进行默认登录页处理,在该过滤器中,维护了很多参数:

arduino 复制代码
    // 登录页地址,默认/login
    private String loginPageUrl;
    // 登出成功页地址,默认/login?logout
    private String logoutSuccessUrl;
    // 登录错误页地址,默认/login?error
    private String failureUrl;
    // 是否开启表单登录
    private boolean formLoginEnabled;
    // 是否开启oauth2登录
    private boolean oauth2LoginEnabled;
    // 是否开启saml2登录
    private boolean saml2LoginEnabled;
    // 认证请求地址,默认/login
    private String authenticationUrl;
    // 用户名参数,默认username
    private String usernameParameter;
    // 密码参数,默认password
    private String passwordParameter;

重定向的GET /login请求则会进入生成登录页 逻辑,调用response直接输出一个页面,并return不再执行后续操作:

那么这个LoginPageHtml是啥呢,其实大家到这里已经可以猜到了,没错就是我们的默认登录页面的HTML,被拼接成了String字符串,最后通过response写出。

我们可以点进去generateLoginPageHtml()这个方法中去查看。

没错,就是我们熟悉的HTML,然后通过StringBuilder拼接然后返回。

最后,我们默认的登录页面就在前端浏览器进行了展示。

5.参考文献在·

6.总结

以上便是本文的全部内容,本人才疏学浅,文章有什么错误的地方,欢迎大佬们批评指正!我是Leo,一个在互联网行业的小白,立志成为更好的自己。

如果你想了解更多关于Leo,可以关注公众号-程序员Leo,后面文章会首先同步至公众号。

相关推荐
艺杯羹2 分钟前
掌握Spring Boot配置艺术:从YAML基础到实战进阶
java·spring boot·后端·yaml
喵叔哟3 分钟前
12.云平台部署
后端·.netcore
rannn_11131 分钟前
【SQL题解】力扣高频 SQL 50题|DAY1
后端·sql·题解
IT_陈寒35 分钟前
JavaScript性能优化:7个V8引擎内部原理帮你减少90%内存泄漏的实战技巧
前端·人工智能·后端
JaguarJack43 分钟前
当遇见 CatchAdmin V5-模块化设计重新定义 Laravel 后台开发
后端·php
Qiuner1 小时前
Spring Boot AOP(三) 通知执行链源码解析
java·spring boot·后端
羑悻的小杀马特1 小时前
【Linux篇章】再续传输层协议TCP:用技术隐喻重构网络世界的底层逻辑,用算法演绎‘网络因果律’的终极推演(通俗理解TCP协议,这一篇就够了)!
linux·网络·后端·tcp/ip·tcp协议
BingoGo1 小时前
当遇见 CatchAdmin V5-模块化设计重新定义 Laravel 后台开发
后端·php
Victor3561 小时前
Netty(23)Netty的负载均衡和高可用性如何实现?
后端
Victor3561 小时前
Netty(24)Netty中的零拷贝文件传输
后端