程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • SpringSecurity

    • Spring Security是什么
    • 认证与授权的基本概念
    • Spring Security 的默认配置
    • SpringSecurity的默认登录页
      • 1.前言
      • 2.涉及过滤器
      • 3.登录页面渲染流程
      • 4.重定向登录页
        • 4.1 抛出 AccessDeniedException
        • 4.2 异常处理
        • 4.3 重定向
        • 4.4 生成默认登录页面
    • Spring Security 的 Filter 机制
    • HttpSecurity 与自定义登录页面
    • Spring Security 的核心组件与扩展
    • Spring Security 中的用户认证与角色管理
    • Spring Security 的授权机制与安全表达式
    • Security 的 Session 与 Token 管理
    • Spring Security 集成第三方登录
    • Spring Security 集成 QQ 登录与 JWT 认证
    • Spring Security 登录认证源码
    • Spring Security - JWT认证实战
    • Spring Security - JWT授权实战
    • Spring Security 异常处理与自定义逻辑
  • SpringSecurity
  • SpringSecurity
scholar
2024-12-29
目录

SpringSecurity的默认登录页

# SpringSecurity的默认登录页

# 1.前言

在 Spring Security 中,默认配置包含一系列过滤器,用于实现安全认证和授权流程。当请求访问一个未被授权的资源时,Spring Security 会重定向用户到默认的登录页面。本文将通过源码分析和测试验证,详细剖析 Spring Security 的默认登录页生成流程。

# 2.涉及过滤器

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

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

# 3.登录页面渲染流程

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

image-20241229162438709

页面渲染力流程:

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

# 4.重定向登录页

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

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

@GetMapping("/test")
public String test() {
            
    return "Hello SpringSecurity6";
}
1
2
3
4
5

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

image-20241229162516043

流程图说明:

  1. 一个用户向其未被授权的资源(/test)发出一个未经认证的请求。
  2. 请求进入SecurityFilterChain开始执行过滤器,在AuthorizationFilter中校验不通过,抛出一个AccessDeniedException。
  3. ExceptionTranslationFilter捕获到异常,调用LoginUrlAuthenticationEntryPoint重定向到/login。
  4. 重定向的/login发起请求进入过滤器
  5. /login会被DefaultLoginPageGeneratingFilter处理,直接响应写出默认登录页。

# 4.1 抛出 AccessDeniedException

访问上述接口地址,在[SpringSecurity6核心过滤器][SpringSecurity6 1]中,有介绍请求最开始是到达FilterChainProxy,由它来调用SecurityFilterChain中的过滤器,/test是没有经过认证的,依次通过下述所有过滤器。

image-20241229162539459

在通过最后一个过滤器AuthorizationFilter中,对当前请求做最后的权限校验,如果没有权限,则会抛出AccessDeniedException:

image-20241229162553772

首先AuthorizationFilter会取出当前用户认证信息,因为当前请求未认证,用户为AnonymousAuthenticationFilter创建的匿名用户:

image-20241229162610508

接着使用AuthorizationManager授权管理器对当前认证信息检查,因为是匿名用户,所以判定当前请求无权访问,抛出AccessDeniedException:

image-20241229162622967

# 4.2 异常处理

抛出的AccessDeniedException异常会被ExceptionTranslationFilter捕获:

image-20241229162638298

ExceptionTranslationFilter根据异常类型进行相应处理:

image-20241229162651230

接着调用handleAccessDeniedException:

image-20241229162703935

接着调用sendStartAuthentication缓存请求,并调用AuthenticationEntryPoint生成认证入口:

image-20241229162717400

# 4.3 重定向

接着调用到LoginUrlAuthenticationEntryPoint的commence进行重定向或者转发:

image-20241229162735740

# 4.4 生成默认登录页面

在经过DefaultLoginPageGeneratingFilter时,进行默认登录页处理,在该过滤器中,维护了很多参数:

// 登录页地址,默认/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;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

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

image-20241229162752620

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

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

image-20231119224144289

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

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

image-20241229162814453

编辑此页 (opens new window)
上次更新: 2024/12/29, 23:35:48
Spring Security 的默认配置
Spring Security 的 Filter 机制

← Spring Security 的默认配置 Spring Security 的 Filter 机制→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式