安全性是没有任何商量余地的。我们要依赖Spring应用程序来传输数据、验证凭据和防止攻击。采用通过设计实现安全防护的原则将能够保护我们的网络避免数据被窃取和未经授权的入侵。
《SpringSecurity实战》展示了如何在造成破坏之前防止跨站脚本和请求伪造攻击。本书将从基础开始讲解,其中将模拟密码升级并添加多种类型的授权。随着技能的增长,读者将可以将Spring Security应用到新的架构中,并创建高级的OAuth2配置。完成之后,读者将拥有一个定制的Spring Security配置,它可以保护应用程序免受常见的和特殊的威胁。
主要内容
●对密码进行编码以及对用户进行身份验证
●端点的安全防护
●安全性测试的 自动化
●设置独立的授权服务器
本书是一本关于 Spring Security 的应用指南,主要讲解了 Spring Security 的基础知识点、核心概念,以及围绕身份验证和授权过程的关键处理流程。书中采取了循序渐进、示例辅助的编写方式,以期让读者能够轻松入门并且随着对本书的深入阅读而能稳步得到技能提升,同时也逐渐加深对于 Spring Security 和身份验证以及授权过程的理解。相信在通读并深刻理解本书的内容之后,读者就能够熟练运用 Spring Security对应用程序的各层进行安全配置。本书提供了许多应用示例,并且根据内容结构的编排还提供了 3 个动手实践的练习章节,这样,读者就能通过每一章的知识内容并且结合实践练习来巩固所学知识。
本书面向使用 Spring 框架构建企业级应用程序的开发人员。每个开发人员都应该从设计阶段就开始考虑应用程序的安全性问题。本书将讲解如何使用 Spring Security配置应用程序级别的安全保障。使用 Spring 开发应用程序,开发人员必须了解如何正确地使用 Spring Security,以及如何在应用程序中应用安全配置。这是非常重要的,如果没有经过体系化的学习和实践就盲目地借助网络资源应用 Spring Security,那么所实现的安全配置势必有所缺失,从而造成应用程序存在漏洞或造成数据泄露的严重问题。
有鉴于此,建议从事 Spring 应用程序开发的人员阅读本书并充分理解其中的内容。
前 言
自2008年以来,我一直担任软件开发工程师和软件开发培训师。可以这么说,虽然我同时喜欢这两个角色,但我还是倾向于成为一个培训师/老师。对我而言,分享知识和帮助他人提高技能一直是我放在首要位置的事情。但我坚信,在这个领域,不能非此即彼。在某种程度上,任何软件开发人员都必须扮演培训师或指导者的角色,如果不首先对如何在真实场景中应用所讲授的内容有一个透彻的理解,就不能胜任软件开发领域的培训师。
随着经验的积累,我逐渐理解了非功能性软件需求的重要性,比如安全性、可维护性、性能等。甚至可以说,我花费在学习非功能性方面的时间比我学习新技术和框架上的时间还多。实际上,发现和解决功能性问题通常比解决非功能性问题要容易得多。这可能就是我遇到的许多开发人员害怕处理混乱的代码、内存相关问题、多线程设计问题,当然还有安全漏洞的原因所在。
当然,安全性是关键的非功能性软件特性之一。而Spring Security是当今应用程序中广泛使用的安全框架之一。这是因为Spring FrameworkSpring生态系统被认为是Java和JVM领域中用于开发企业应用程序的技术的领导者。
但我特别关注的是,人们在学习正确使用Spring Security保护应用程序免受常见漏洞侵害时所面临的困难。人们总是可以在网上找到关于Spring Security的所有详细信息。但是,要将它们按照正确的顺序组合在一起以便只需花费少的精力就可以使用该框架,还需要花费大量的时间和积累大量的经验。此外,不完整的知识可能会导致人们创建出难以维护和开发的解决方案,甚至可能暴露安全漏洞。很多时候,从事应用程序开发的团队都会向我咨询,发现Spring Security使用不当。而且,在许多情况下,其主要原因是对如何使用Spring Security缺乏透彻的理解。
正因为如此,我决定写一本书来帮助Spring开发人员理解如何正确使用Spring Security。《Spring Security实战》应该成为一项资源,帮助那些不了解Spring Security的人逐渐理解它。归根结蒂,我希望《Spring Security实战》能给读者带来巨大的价值,让他们节省学习Spring Security的时间,以及避免在应用程序中引入所有可能的安全漏洞。
Lauren?iu Spilc?是Endava极为敬业的一位领导和培训师,在Endava,他领导着一个为北欧国家的金融市场所开发的项目。此前,他是一名软件开发人员,构建了全球广泛安装应用的型的企业资源规划解决方案之一。
Lauren?iu坚信,重要的不仅仅是交付高质量的软件,分享知识,帮助他人学习和提高技能也是很重要的。这促使他设计和讲授与Java技术相关的课程,并且在美国和欧洲各地进行演讲以及参与研讨会。他的演讲活动包括Voxxed Days、TechFlow、Bucharest Technology Week、JavaSkop、Oracle Code Explore、OReilly Software Architecture和Oracle Code One。
目 录
第I部分 初 识
第1 章 安全性现状 3
1.1 Spring Security的定义与用途 4
1.2 什么是软件安全性 7
1.3 安全性为什么重要 12
1.4 Web应用程序中的常见安全漏洞 13
1.4.1 身份验证和授权中的漏洞 14
1.4.2 什么是会话固定 15
1.4.3 什么是跨站脚本(XSS) 16
1.4.4 什么是跨站请求伪造(CSRF) 17
1.4.5 理解Web应用程序中的注入漏洞 18
1.4.6 应对敏感数据暴露 18
1.4.7 缺乏方法访问控制指的是什么 21
1.4.8 使用具有已知漏洞的依赖项 23
1.5 各种架构中所应用的安全性 23
1.5.1 设计一个单体式Web应用程序 24
1.5.2 为前后端分离设计安全性 25
1.5.3 理解OAuth 2流程 27
1.5.4 使用API键、加密签名和IP验证保护请求 29
1.6 本书知识内容 30
1.7 本章小结 31
第2 章 Spring Security初探 33
2.1 开始构建首个项目 34
2.2 默认配置有哪些 39
2.3 重写默认配置 43
2.3.1 重写UserDetailsService组件 44
2.3.2 重写端点授权配置 48
2.3.3 以不同方式设置配置 50
2.3.4 重写AuthenticationProvider实现 54
2.3.5 在项目中使用多个配置类 58
2.4 本章小结 60
第Ⅱ部分 实现
第3 章 管理用户 63
3.1 在Spring Security中实现身份验证 64
3.2 描述用户 66
3.2.1 阐明UserDetails契约的定义 66
3.2.2 GrantedAuthority契约详述 68
3.2.3 编写UserDetails的小化实现 69
3.2.4 使用构造器创建UserDetails类型的实例 72
3.2.5 合并与用户相关的多个职能 73
3.3 指示Spring Security如何管理用户 77
3.3.1 理解UserDetailsService契约 77
3.3.2 实现UserDetailsService契约 78
3.3.3 实现UserDetailsManager契约 82
3.4 本章小结 90
第4 章 密码处理 91
4.1 理解PasswordEncoder契约 91
4.1.1 PasswordEncoder契约的定义 92
4.1.2 实现PasswordEncoder契约 93
4.1.3 从PasswordEncoder提供的实现中选择 95
4.1.4 使用DelegatingPasswordEncoder实现多种编码策略 98
4.2 Spring Security Crypto模块的更多知识 102
4.2.1 使用密钥生成器 102
4.2.2 将加密器用于加密和解密操作 104
4.3 本章小结 106
第5 章 实现身份验证 107
5.1 理解AuthenticationProvider 109
5.1.1 在身份验证期间表示请求 110
5.1.2 实现自定义身份验证逻辑 111
5.1.3 应用自定义身份验证逻辑 113
5.2 使用SecurityContext 117
5.2.1 将一种保持策略用于安全上下文 119
5.2.2 将保持策略用于异步调用 121
5.2.3 将保持策略用于独立应用程序 123
5.2.4 使用DelegatingSecurityContextRunnable转发安全上下文 124
5.2.5 使用DelegatingSecurityContextExecutorService转发安全上下文 127
5.3 理解HTTP Basic和基于表单的登录身份验证 129
5.3.1 使用和配置HTTP Basic 130
5.3.2 使用基于表单的登录实现身份验证 133
5.4 本章小结 140
第6 章 动手实践:一个小型且安全的Web应用程序 141
6.1 项目需求和设置 141
6.2 实现用户管理 148
6.3 实现自定义身份验证逻辑 153
6.4 实现主页面 156
6.5 运行和测试应用程序 159
6.6 本章小结 161
第7 章 配置权限:限制访问 163
7.1 基于权限和角色限制访问 165
7.1.1 基于用户权限限制所有端点的访问 167
7.1.2 基于用户角色限制所有端点的访问 175
7.1.3 限制对所有端点的访问 180
7.2 本章小结 183
第8 章 配置权限:应用限制 185
8.1 使用匹配器方法选择端点 185
8.2 使用MVC匹配器选择用于授权的请求 192
8.3 使用Ant匹配器选择用于授权的请求 200
8.4 使用正则表达式匹配器选择用于授权的请求 204
8.5 本章小结 210
第9 章 实现过滤器 211
9.1 在Spring Security架构中实现过滤器 213
9.2 在过滤器链中现有过滤器之前添加过滤器 215
9.3 在过滤器链中已有的过滤器之后添加过滤器 219
9.4 在过滤器链中另一个过滤器的位置添加一个过滤器 222
9.5 Spring Security提供的Filter实现 227
9.6 本章小结 229
第10 章 应用CSRF防护和CORS 231
10.1 在应用程序中应用跨站请求伪造(CSRF)防护 231
10.1.1 CSRF防护如何在Spring Security中发挥作用 232
10.1.2 在实际场景中使用CSRF防护 238
10.1.3 自定义CSRF防护 244
10.2 使用跨源资源共享 255
10.2.1 CORS的运行机制 256
10.2.2 使用@CrossOrigin注解应用CORS策略 261
10.2.3 使用CorsConfigurer应用CORS 262
10.3 本章小结 263
第11 章 动手实践:职责分离 265
11.1 示例的场景和需求 266
11.2 实现和使用令牌 269
11.2.1 令牌是什么 269
11.2.2 JSON Web Token是什么 272
11.3 实现身份验证服务器 274
11.4 实现业务逻辑服务器 285
11.4.1 实现Authentication对象 290
11.4.2 实现身份验证服务器的代理 292
11.4.3 实现AuthenticationProvider接口 295
11.4.4 实现过滤器 297
11.4.5 编写安全性配置 304
11.4.6 测试整个系统 306
11.5 本章小结 307
第12 章 OAuth 2的运行机制 309
12.1 OAuth 2框架 310
12.2 OAuth 2身份验证架构的组件 312
12.3 使用OAuth 2的实现选项 313
12.3.1 实现授权码授权类型 313
12.3.2 实现密码授权类型 318
12.3.3 实现客户端凭据授权类型 320
12.3.4 使用刷新令牌获得新的访问令牌 321
12.4 OAuth 2的弱点 323
12.5 实现一个简单的单点登录应用程序 324
12.5.1 管理授权服务器 325
12.5.2 开始实现 328
12.5.3 实现ClientRegistration 330
12.5.4 实现ClientRegistrationRepository 333
12.5.5 Spring Boot配置的纯粹方式 335
12.5.6 获取经过身份验证的用户的详细信息 337
12.5.7 测试应用程序 338
12.6 本章小结 341
第13 章 OAuth 2:实现授权服务器 343
13.1 编写我们自己的授权服务器实现 345
13.2 定义用户管理 346
13.3 向授权服务器注册客户端 349
13.4 使用密码授权类型 353
13.5 使用授权码授权类型 355
13.6 使用客户端凭据授权类型 361
13.7 使用刷新令牌授权类型 364
13.8 本章小结 366
第14 章 OAuth 2:实现资源服务器 367
14.1 实现资源服务器 369
14.2 远程检查令牌 372
14.3 实现带有JdbcTokenStore的黑板模式 380
14.4 两种方法的简要对比 389
14.5 本章小结 390
第15 章 OAuth 2:使用JWT和加密签名 391
15.1 使用JWT以及对称密钥签名的令牌 391
15.1.1 使用JWT 392
15.1.2 实现授权服务器以颁发JWT 393
15.1.3 实现使用JWT的资源服务器 398
15.2 使用通过JWT和非对称密钥签名的令牌 402
15.2.1 生成密钥对 403
15.2.2 实现使用私钥的授权服务器 405
15.2.3 实现使用公钥的资源服务器 407
15.2.4 使用一个暴露公钥的端点 409
15.3 将自定义详细信息添加到JWT 413
15.3.1 配置授权服务器以便向令牌添加自定义详细信息 414
15.3.2 配置资源服务器以读取JWT的自定义详细信息 416
15.4 本章小结 419
第16 章 全局方法安全性:预授权和后授权 421
16.1 启用全局方法安全性 422
16.1.1 理解调用授权 422
16.1.2 在项目中启用全局方法安全性 425
16.2 对权限和角色应用预授权 426
16.3 应用后授权 431
16.4 实现方法的许可 436
16.5 本章小结 448
第17 章 全局方法安全性:预过滤和后过滤 451
17.1 为方法权限应用预过滤 452
17.2 为方法授权应用后过滤 459
17.3 在Spring Data存储库中使用过滤 463
17.4 本章小结 470
第18 章 动手实践:一个OAuth 2 应用程序 471
18.1 应用程序场景 472
18.2 将Keycloak配置为授权服务器 474
18.2.1 为系统注册一个客户端 478
18.2.2 指定客户端作用域 479
18.2.3 添加用户并获取访问令牌 481
18.2.4 定义用户角色 485
18.3 实现资源服务器 490
18.4 对应用程序进行测试 501
18.4.1 证明经过身份验证的用户只能为自己添加记录 502
18.4.2 证明用户只能检索自己的记录 504
18.4.3 证明只有管理员才能删除记录 505
18.5 本章小结 506
第19 章 在反应式应用程序中使用Spring Security 509
19.1 什么是反应式应用程序 510
19.2 反应式应用程序中的用户管理 514
19.3 在反应式应用程序中配置授权规则 519
19.3.1 在反应式应用程序的端点层应用授权 520
19.3.2 在反应式应用程序中使用方法安全性 526
19.4 反应式应用程序和OAuth 2 529
19.5 本章小结 532
第20 章 Spring Security测试 535
20.1 使用模拟用户进行测试 537
20.2 使用UserDetailsService提供的用户进行测试 545
20.3 将自定义Authentication对象用于测试 547
20.4 测试方法安全性 551
20.5 测试身份验证 552
20.6 测试CSRF配置 556
20.7 测试CORS配置 557
20.8 测试反应式Spring Security实现 558
20.9 本章小结 561
附录A 创建一个Spring Boot
项目 563