【Spring Security详解】第一章 | 概述

这篇具有很好参考价值的文章主要介绍了【Spring Security详解】第一章 | 概述。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

从本系列开始,博主将带来大家深入学习Spring Security。博主对该框架的看法是不但要会使用,还有能够理解其源码,要知其然,还要知其所以然。
相信朋友们阅读完博主本系列全部文章之后,定会理解Spring Security,让我们从入门、到理解、最终吊打面试官!

PS:博主早在8月中旬开始写本系列博客,本来想一文搞定Spring Security,但由于Spring Security的细节特别多,已经写了2w字却感觉才将心中所想写了近半不到,因此萌生了想写Spring Security体系一系列文章的想法。还请多多关注博主,不胜感激!

在本篇内容,博主给大家介绍一下Spring Security在市场上的使用情况,以及Spring Security是通过什么原来完成认证操作的(梗概)。同时也涉及Spring Security的源码结构,可能不太易懂,建议配合本系列文章食用。

一、 Spring Security简介

在Java企业开发中,市面上常见的开源安全框架非常少,主要有以下几种方案:

  • Shiro
  • Spring Security
  • 企业自行开发的方案

几年前,微服务还没有大火的时候,Shiro以其轻量、简单、易于集成的优点独当一面。
而最近今年,随着微服务的大火,Spring Security作为Spring家族的首推的安全框架,在与Spring等其他组件的无缝整合的特点,导致其市面占有率也是逐年提高。

二、 Spring Security提供了哪些功能

Spring Security是Spring全家桶里面的一个项目,提供认证、授权以及应对漏洞攻击的保护。

  • 认证authentication: 可以简单理解成”你是谁“,最简单的例子就是用户登录,这就是认证,下文中登录操作代表认证
  • 授权authorization:可以简单理解成“你有哪些权限,你能做什么”,比如登录进来的用户是具有管理员或是普通用户的权限。
  • 保护protection:应对遭受漏洞利用的保护。

三、 Spring Security是如何完成认证的

Spring Security通过一系列过滤器完成认证与授权的工作。

对于SpringBoot工程,并没有引入其他依赖。
客户端发起请求时,tomcat容器会创建一个包括Filter和Servlet的FilterChain(过滤器链)。通过Filter可以控制请求与响应,以及是否调用下游的过滤器或Servlet。
【Spring Security详解】第一章 | 概述

接来下博主简要说明下Spring Security中起到核心作用的几个类,这是通过这几个类Spring Security才能集成到SpringBoot当中,并发挥作用。


此处参考了Spring Security的官网文档:链接: Spring Security官方文档

3.1 DelegatingFilterProxy

Spring Seucrity实现认证与授权的功能提供了很多过滤器,通过这些过滤器来拦截请求,并做相应处理。那么如何将这些过滤器嵌入到Spring的IOC容器呢,最好的做法就是将Spring Security这些过滤器注册成Bean,这样就可以统一的进行管理了,DelegatingFilterProxy就是为了实现这个目的。

Delegating这个名字很绕口ˈdelɪɡeɪtɪŋ' ,是委托的意思。DelegatingFilterProxy合到一起就是委托过滤器代理
整体意思就是DelegatingFilterProxy是一个代理,他委托了某个类(FilterChainProxy 下文会提到),并让那个类完成后续拦截操作。
可以把他理解成一个胶水,由他连接了web应用的原生过滤器和Spring Security的过滤器。
【Spring Security详解】第一章 | 概述

DelegatingFilterProxy是一个过滤器,里面有个成员变量

	private volatile Filter delegate;

他就是委托对象。

在客户端请求来临的时候会执行doFilter()方法。
首先会判断delegate是否为空,若为空的话从IOC容器中通过getBean()的方法拿到这个代理对象FilterChainProxy

protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
		String targetBeanName = getTargetBeanName();
		Assert.state(targetBeanName != null, "No target bean name set");
		Filter delegate = wac.getBean(targetBeanName, Filter.class);
		if (isTargetFilterLifecycle()) {
			delegate.init(getFilterConfig());
		}
		return delegate;
	}

并执行代理对象的doFilter()方法。

	protected void invokeDelegate(
			Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		delegate.doFilter(request, response, filterChain);
	}

这样后续的操作就交由这个代理对象去做了。

3.2 FilterChainProxy & SecurityFilterChain(二者关系密切,放一起讲述)

FilterChainProxy这个类可以理解成过滤器链代理。DelegatingFilterProxy正是委托给FilterChainProxy,就是上文提到的delegate来完成拦截等操作。

FilterChainProxy是Spring Security发挥作用的入口,一切Spring Security的过滤器都是从这之后开始调用的。

另外值得注意的是,DelegatingFilterProxy是注册到Tomcat容器的一个过滤器,他的生命周期由Tomcat来控制。而FilterChainProxy则是Spring的IOC容器中的一个Bean。
【Spring Security详解】第一章 | 概述
这幅图展示了客户端client请求到系统中时,经过Tomcat的某些原生过滤器后,到达DelegatingFilterProxy。并委托给FilterChainProxy,而FilterChainProxy通过SecurityFilterChain来代理各种Filter实例。之后再到Tomcat的原生过滤器,最终到达Servet。
简而言之,FilterChainProxy使用SecurityFilterChain确定应对此请求调用哪些Spring Security过滤器。

【Spring Security详解】第一章 | 概述
可以看到delegate对象中包括一个过滤器链的列表(SecurityFilterChain)。其中DefaultSecurityFilterChain对象就是Spring Security的一个过滤器链,如前一个图片所示的SecurityFilterChain

FilterChainProxy作为一个代理类,他的doFilter()方法最终会调到下面的doFilterInternal()

private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		FirewalledRequest firewallRequest = this.firewall.getFirewalledRequest((HttpServletRequest) request);
		HttpServletResponse firewallResponse = this.firewall.getFirewalledResponse((HttpServletResponse) response);
		List<Filter> filters = getFilters(firewallRequest);
		if (filters == null || filters.size() == 0) {
			if (logger.isTraceEnabled()) {
				logger.trace(LogMessage.of(() -> "No security for " + requestLine(firewallRequest)));
			}
			firewallRequest.reset();
			chain.doFilter(firewallRequest, firewallResponse);
			return;
		}
		if (logger.isDebugEnabled()) {
			logger.debug(LogMessage.of(() -> "Securing " + requestLine(firewallRequest)));
		}
		// 看这里
		VirtualFilterChain virtualFilterChain = new VirtualFilterChain(firewallRequest, chain, filters);
		virtualFilterChain.doFilter(firewallRequest, firewallResponse);
	}

将后续的执行操作交由他的一个内部静态类去实现。执行VirtualFilterChain#doFilter()方法。

	@Override
		public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
			if (this.currentPosition == this.size) {
				if (logger.isDebugEnabled()) {
					logger.debug(LogMessage.of(() -> "Secured " + requestLine(this.firewalledRequest)));
				}
				// Deactivate path stripping as we exit the security filter chain
				this.firewalledRequest.reset();
				this.originalChain.doFilter(request, response);
				//退出循环
				return;
			}
			this.currentPosition++;
			// 执行Spring Security的过滤器
			Filter nextFilter = this.additionalFilters.get(this.currentPosition - 1);
			if (logger.isTraceEnabled()) {
				logger.trace(LogMessage.format("Invoking %s (%d/%d)", nextFilter.getClass().getSimpleName(),
						this.currentPosition, this.size));
			}
			nextFilter.doFilter(request, response, this);
		}

在这里面会循环的调用每个Spring Security提供的过滤器进行各种拦截处理操作,并在最后退出循环,进入Tomcat的其他过滤器中…
【Spring Security详解】第一章 | 概述

3.3 多个SecurityFilterChain

在Spring Security中,可以配置多个SecurityFilterChain,由FilterChainProxy 决定应使用哪个SecurityFilterChain

FilterChainProxy 会根据请求的路由匹配第一个符合条件的SecurityFilterChain,并执行其过滤器。
【Spring Security详解】第一章 | 概述

四、 Spring Security的初步使用

很多人对Spring Security的感觉都是太繁琐,其实到了微服务的天下,Spring Security的使用非常简单。
接下来博主以一个简单的例子给大家演示一下。

4.1 集成Spring Security

引入pom依赖。

 		<!--标识一个springboot的web工程-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <!--引入Spring Security-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

Spring Security是通过一系列过滤器来完成认证与授权的功能的。客户端请求之后逐个通过Spring Security的各种过滤器。当引入Spring Security依赖时,其实已经加载了Spring Security提供的许多个默认过滤器。

添加请求URL,当做用来测试的资源URL。

@RequestMapping("hello")
public class HelloController {
    @GetMapping()
    public String hello() {
        return "hello";
    }
}

启动项目,可以看到控制台输出的日志中,包括了如下的内容。
按照Spring Security官网的描述,其实生成了名为user的用户,密码为如下71c36beb-7af5-4116-b807-ab84e484e6fa
并且可以看到控制台打印了Spring Security默认加载的15个过滤器,正是他们支撑着Spring Security做到了认证相关的操作。
稍后博主会挑常见的过滤器给大家说明一下,值得注意的是,这15个过滤器的先后执行顺序就是控制台打印的顺序。

Using generated security password: 71c36beb-7af5-4116-b807-ab84e484e6fa

2022-08-22 20:22:07.179  INFO 10672 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: any request, [
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@4784013e,  
org.springframework.security.web.context.SecurityContextPersistenceFilter@2ca6546f,  
org.springframework.security.web.header.HeaderWriterFilter@aa10649,  
org.springframework.security.web.csrf.CsrfFilter@c4c0b41,  
org.springframework.security.web.authentication.logout.LogoutFilter@3af356f, 
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@267517e4, 
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@231baf51, 
org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@6f952d6c, 
org.springframework.security.web.authentication.www.BasicAuthenticationFilter@56ba8773, 
org.springframework.security.web.savedrequest.RequestCacheAwareFilter@7923f5b3, 
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@6050462a, 
org.springframework.security.web.authentication.AnonymousAuthenticationFilter@5965844d, 
org.springframework.security.web.session.SessionManagementFilter@37095ded, 
org.springframework.security.web.access.ExceptionTranslationFilter@368d5c00, 
org.springframework.security.web.access.intercept.FilterSecurityInterceptor@1763992e 
]

4.2 访问测试

接下来使用浏览器访问该资源。请求地址http://localhost:8080/hello(SpringBoot默认启动端口为8080)
可以观察到页面直接跳转到了http://localhost:8080/login并打开了一个登录页面。
【Spring Security详解】第一章 | 概述
F12可以看到页面请求http://localhost:8080/hello之后,返回响应302,并重定向到http://localhost:8080/login接口进行请求,该接口响应为一个页面。让我们完成登录操作。
【Spring Security详解】第一章 | 概述
输入账号密码后,点击登录(用户:user,密码:71c36beb-7af5-4116-b807-ab84e484e6fa),此时可以看到页面返回了接口hello,这也意味着只有认证成功才会允许访问资源。

这就是Spring Security的魅力。博主只是引入了一个Spring Security依赖就做到了所有资源的保护,那他是怎么做到的呢,且听我慢慢道来。

4.3 为什么默认访问资源会返回登录页面?

【Spring Security详解】第一章 | 概述

该图片来自《深入浅出Spring Security》

当客户端发起一个资源的请求时(http://localhost:8080/hello),会经过上文所述的15个Spring Security的过滤器依次执行。

直到走到FilterSecurityInterceptor这个过滤器的时候,抛出一个访问被拒绝的异常。【Spring Security详解】第一章 | 概述
此处代码走到AbstractSecurityInterceptor类的原因是FilterSecurityInterceptor的doFilter()调用到了父类的代码,在父类的方法中抛出了AccessDeniedException,该异常会继续往上抛出。

直到ExceptionTranslationFilter的catch模块捕获到了这个异常。
【Spring Security详解】第一章 | 概述
并最终调用

authenticationEntryPoint.commence(request, response, reason);

【Spring Security详解】第一章 | 概述
最终将请求重定向到http://localhost:8080/login页面。
【Spring Security详解】第一章 | 概述

紧接着,客户端再次向服务请求http://localhost:8080/login

老规矩又开始按顺序执行这15个过滤器,直到到达DefaultLoginPageGeneratingFilter过滤器的时候,会判断若是访问登录请求URL或是登录失败或是退出成功中的一个,会执行下面的逻辑。
【Spring Security详解】第一章 | 概述
很明显isLoginUrlRequest(request) == true
然后代码来到了generateLoginPageHtml()
可以看到通过StringBuilder拼接了一个HTML的登录页面。
【Spring Security详解】第一章 | 概述
后续操作就是往response写入了这个html的登录页面,并返回。所以就有了当初请求http://localhost:8080/hello时,出现了一个登录页面。

这便是集成Spring Security后,Spring Security的默认安全策略。

博主简单梳理一下这块逻辑。

  1. 客户端请求一个资源URL。
  2. 请求会按照顺序经过Spring Security默认提供的15个过滤器,在FilterSecurityInterceptor过滤器中发现用户没有认证会抛出AccessDeniedException异常。
  3. 异常会被ExceptionTranslationFilter过滤器被捕获到,并调用authenticationEntryPoint#commence方法将请求重定向到/login接口。
  4. 客户端再次请求/login接口。
  5. 请求被DefaultLoginPageGeneratingFilter过滤器拦截,并生成了一个登录页面并返回给客户端。

五、 小结

本章博主主要给大家介绍了Spring Security在市场上的使用情况,以及Spring Security的整体架构。并举了一个简单的例子说明为什么仅仅引入了Spring Security的maven依赖就对资源做了保护。
接下来博主会带来大家进一步理解Spring Security的认证细节,尽情期待!文章来源地址https://www.toymoban.com/news/detail-402128.html

到了这里,关于【Spring Security详解】第一章 | 概述的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 第一章 IMS概述

    1.1 什么是IMS IMS是IP多媒体子系统(IP Multimedia Subsystem)的缩写,有两个最主要的特点: 1)是一个基于全IP的完整语音方案: - 全IP是指IMS所使用的协议、接口都是遵循TCP/IP协议栈。这个主要是和2/3G时代的CS(电路交换)语音方案对比来说的,因为CS里使用了大量的非IP协议如

    2024年02月09日
    浏览(41)
  • 【计算机网络】第一章 概述

    目录 1.1 计算机网络在信息时代中的作用 1.2 互联网概述 1.2.1  网络的网络 1.2.2  互联网基础结构发展的三个阶段 1.2.3  互联网的标准化工作 1.3 互联网的组成 1.3.1  互联网的边缘部分 a. 客户-服务器方式(C/S 方式) b. 对等连接方式(P2P 方式) 1.3.2  互联网的核心部分 a. 电路

    2024年03月22日
    浏览(58)
  • 计算机网络(第一章)——概述

    1 网络、互连网(互联网)和因特网 网络(Network)由若干 结点(Node) 和连接这些结点的 链路(Link) 组成。 多个网络还可以通过路由器互连起来,这样就构成了一个覆盖范围更大的网络,即互联网(或互连网因此,互联网是“ 网络的网络(Netwrok of Networks) \\\"。 因特网(Internet)是世界上最

    2024年02月04日
    浏览(45)
  • 第一章 人工智能安全概述

    1.1 什么是人工智能安全 目前并没有统一的定义,人工智能安全是人工智能与网络安全的交叉学科,两个学科已经建立了深厚的理论和技术体系,进一步看清两个学科的交叉点的逻辑关系是理解人工智能安全的关键。 攻击与防御 对于防御者而言,使用人工智能新技术加强网络

    2024年02月04日
    浏览(49)
  • 【计算机网络】第一章——概述

    ========================================================================= 个人主页直达: 小白不是程序媛 系列专栏: 计算机网络基础 ========================================================================= 目录 前言 计算机网络概述 概念 功能 组成 分类 标准化工作 性能指标 速率 带宽 吞吐量 时延 时延带

    2024年02月07日
    浏览(57)
  • 【计算机网络】第一章 概述(上)

    1.2.1 网络、互连网(互联网)和因特网 网络 :网络由若干 结点 和连接这些结点的 链路 组成。 互联网 :多个网络通过路由器互联起来,就构成了一个覆盖范围更大的网络,即互联网。 因特网 :是世界上最大的互联网络。 1.2.2 因特网发展的三个阶段 1.2.4 因特网的组成 边缘

    2024年02月09日
    浏览(49)
  • 计算机网络(湖科大)第一章 概述

    计算机网络已由一种 通信基础设施 发展成为一种重要的 信息服务基础设施 。 计算机网络已经像水,电,煤气这些基础设施一样,成为我们 生活中不可或缺 的一部分 我国互联网发展状况 ✨1.2.1 网络、互联网和因特网 网络:网络(Network)由若干 结点 (Node)和连接这些结

    2024年01月21日
    浏览(50)
  • 第一章 计算机系统的概述①

    概念 :操作系统 (Operating System, 0s) 是指 控制和管理 整个计算机系统的 硬件和软件 资源,并合理地组织调度计算机的工作和资源的分配: 以提供给用户和其他软件方便的接口和环境 ;它是计算机系统中最基本的 系统软件。 根据操作系统的定义,操作系统的三个特点:1)操

    2024年02月11日
    浏览(51)
  • 计算机网络第一章概述

    因特网(Internet) 是世界上最大的互连网络【小写 i 的 internet 是通用名词,互连的网络都叫 internet 】 因特网的前身是1969年创建的第一个分组交换网:ARPANT 普通用户如何接入因特网? 通过 ISP 接入因特网。 ISP 可以从因特网管理机构申请到成块的 IP 地址,同时拥有通信线路以及

    2024年02月15日
    浏览(57)
  • 《人工智能》第三版 第一章 概述 课后习题

    第一章 讨论题 1.你如何定义人工智能? 人工智能利用计算机和机器模仿人类大脑解决问题和决策的能力 2.区分强人工智能和弱人工智能。 区分强人工智能和弱人工智能的关键在于它们的功能和应用范围:强人工智能能够执行任何人类智能任务,而弱人工智能则专注

    2024年01月25日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包