7. Spring Boot2.5 安全机制与 REST API 身份验证实战
Posted 天空鸟_时光不老
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了7. Spring Boot2.5 安全机制与 REST API 身份验证实战相关的知识,希望对你有一定的参考价值。
文章目录
Spring Boot2.5 安全机制与 RESTAPI 身份验证实战
内容简介:
一、Java Spring Boot 2.5 安全机制
二、Java Spring Boot 2.5 安全实战
一、Java Spring Boot 2.5 安全机制
本节课讲的是应用程序安全问题,在 Spring Boot 体系里,提供了一套安全机制,
可以对接各种不同的安全框架,包括自定义实现原始的身份验证机制。
模拟简单的 REST API 项目,启用身份验证,进行扩展对接 mysql 数据库,甚至对
接 Release 缓存,实现整个用户的注册和身份验证过程。
但大型项目,比如淘宝、微信、新浪微博的账号验证基本上都在 Release 里面进行,
用户的规模比较大,而且整个的用户会话信息,要在分布式缓存里面进行保存。后面可
以扩展到 Release 身份验证机制,把身份验证与 Release 和 MySQL 结合起来,实现一个
完整的项目。
Spring Boot 提供的安全机制,可以用 Spring Security 开源框架,也可以用
Apache Shiro 开源框架,还可以用自定义实现安全验证。Web 框架开发底层本质上是
Web 请求进入 Web 框架,然后可以拦截,这里也叫 AOP 编程,用于做拦截,做身份验
证的工作。总结:
1)自定义实现安全验证;
2)Apache Shiro 开源框架;
3)Spring Security 开源框架;
4)大量使用 AOP;
5)依赖注入思想;
6)灵活扩展。
2. ### Java Spring Boot 2.5 安全机制
也可以进行授权,定了一些角色,设置对应的权限,这里支持的方式很多。Spring
Boot 作为快速开发框架,底层有 Web 开发的接口,可以做网站、 API 应用、定时任务
应用等等。
目前应用程序身份验证的类型非常多,不仅基于网页的 Form 表单验证、Basic、摘
要身份验证、令牌身份验证,令牌身份验证主要是用在 REST API,包括一些大型的微服
务架构程序中。当然还有企业级身份验证,比如基于企业局域网的客户身份验证,组织
内部使用的身份验证。还有跨第三方平台的开放式身份验证体系等。
后续基于 Spring Boot 进行开发,尽量升级到比较新的版本,最好是 Spring Boot
2.3 以上的版本,不要用太老的版本。Spring Boot 2020 年 9 月份又修复了一批安全漏
洞,涉及到远程代码过程执行的安全漏洞问题。
安全漏洞建议总结:
1)Spring Boot 2020 年 9 月份修复漏洞;
2)Spring Boot Actuator 未授权访问远程代码执行漏洞;
3)紧急修复 Spring Framework 版本包含一个安全漏洞(CVE-2020-5421)的修
复程序。此漏洞可以通过 sessionId 绕过 RFD (反射型文件下载)保护;
4)Spring Boot 2018 年修复了一些安全漏洞;
5)建议使用最新的 Spring 5.0+版本;
6)Spring 框架升级 5.0.0 - 5.0.2;
7)Spring 框架升级 4.3.0 - 4.3.13;
8)Spring Boot 1.5.10。
安全框架本身相对成熟,可以集成 Spring Security,也可以集成 Spring MVC,也
可以集成 Spring Boot,也可以集成 Spring cloud。
保护 Spring 应用系统的安全标准,可以实施各种产同的身份验证,可以做各种数据
源进行集成,定制开发工作,包括基于角色、基于令牌都可以实现。这种多种身份验证
机制的支持,包括扩展 URL、自定义路由规则,这种方法的验证都可以进行实现。这种
框架方便构建安全体系,不会限制应用程序的类型。整个集成和 Spring 应用平台集成的
最好。总结:
1)Spring Security 功能强大且高度可自定义的安全框架;
2)保护 Spring 应用系统的安全标准;
3)Spring Security 专注于身份验证和授权;
4)容易地扩展、自定义开发;
5)前身是 Acegi Security;
6)提供安全认证服务的框架;
7)Spring Security 为基于 J2EE 企业应用提供了全面安全机制;
8)Authentication 验证和 Authorization 授权;
9)抵御会话攻击, 点击劫持,CSRF 跨站请求伪造。
Apache 官网有一个开源的项目叫 Apache Shiro,是一个开源的安全管理,支持的
工作非常强大,唯一的差别是不属于 Spring 官方。但是很好用,有很多项目包括
Spring Boot,甚至 Spring Cloud 都在使用 Apache Shiro。对接不同的数据源,两个
都可以,取决于个人倾向,两个都非常完善,正常情况下,如果希望技术上简单一点,
可以直接使用一整套 Spring。Java 安全框架 Shiro 总结:
1)Apache Shiro 简单易用的开源 Java 安全框架;
2)轻松实现身份验证、授权、加密和会话管理;
3)使用 Shiro 可以快速实现系统安全;
4)Shiro 其前身是 Jsecurity 项目;
5)Shiro 可以轻易实现 Java 网站安全验证;
6)可应用于 Web 环境,非 Web 环境;
7)支持多种数据源 MySQL 等;
8)如 LDAP,JDBC,Kerberos,ActiveDirectory 等)。
二、Java Spring Boot 2.5 安全实战
在之前的 WEB 架构基本上,可以加入门的 starter-security 的依赖,入完以后,会
提供必要的安全组件,默认的就是 security 组件,当然也可以替换,两个都可以配置。
实现代码如下:
<dependencies>
... <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId> spring-boot-starter-security </artifactId>
</dependency>
... </dependencies>
2. WebSecurityConfig
早期的 Spring1.x 几版本中,需要自己显示去关闭或者开放安全验证,现在的基本
上默认是已经启动了。可以直接设置 WebSecurityConfig 配置文件,注入必要的安全配
置规则,比如基于某个内路由规则、针对 order 订单的身份验证等,甚至加入角色的限
制都可以实现,提供了强大的规则。
WebSecurityConfig 总结:
1)Spring Security 的配置类;
2)WebSecurityConfig;
3)可以配置安全规则;
4)默认启用 basic 验证;
5)# Spring Security 可以在配置文件中关闭;
6)security.basic.enabled = false。
下面这段代码,是 Web 全站安全验证配置的例子,针对 anyRequest 定制时,所有
的请求都做身份验证。hasRole 表示针对当前的请求访问某个地址,或者所有的请求访
问时是否具备某个角色。当然这个角色或者权限的验证,需要定制扩展接口就可以了。
比如连数据库或者连缓存,实现角色查询,有校验就可以了。
@ Configuration
@ (SecurityProperties.BASIC_AUTH_ORDER - 10)
public class ApplicationConfigurerAdapter extends
WebSecurityConfiguerAdapter
@Override
protected void configure( http) throws
http.antMatcher("/admin/**")
.authorizeRequests()
.antMatchers("/admin/users").hasRole(“usersAdmin")
.antMatchers("/admin/orders").hasRole(“ordersAdmin")
.anyRequest().isAuthenticated();
当然有一般规则,就有特殊规则,允许自定义扩展底层的 API 实现自定义的判断逻
辑,这是良好的安全框架所具备的功能。重新实现验证机制:
WebSecurityConfig 安全配置类;
UserDetailsService 接口。
实践案例演示:
这个程序是之前的 Web 网站,看一下项目的依赖,通过文件依赖可以看出,相比之
前的项目,数据库依然存在,还是用之前的 spring data jpa,加入 MySQL 的数据库的链
接。
后面稍微注意一下,这里面有个 starter security,加完以后,可以看一下左边的依
赖包的安全组件,有包括 spring security config 、spring security core、spring
security web 等。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rXk7xLDd-1667549379431)(https://cdn.jsdelivr.net/gh/WaterMoonMirror/typora-img/img/202211041502395.png)]
下面看一下,代码具体的配置和实现,新版本默认已经集成,现在最主要的要有
Web 安全配置,全局配置的时候使用内存验证,实际可以对接数据库、对接缓存。当前
程序的进程里面写了用户名“frankxu”,密码“1234qwer”,这种方式并不提倡。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WTNmYJvR-1667549379431)(https://cdn.jsdelivr.net/gh/WaterMoonMirror/typora-img/img/202211041524449.png)]
正常情况下,可以定义特殊规则“configuer”,针对 rize 请求,可以匹配首页,允许
首页所有的人都可以访问;针对 user,做身份验证。也可以提供表单的登录模式
“formLogin()”。做这个例子,是提供这种访问 HOME 可以不做身份验证的方法,可以
直接进入。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-faIxJN1F-1667549379432)(https://cdn.jsdelivr.net/gh/WaterMoonMirror/typora-img/img/202211041525222.png)]
查询数据库 Get all,演示在浏览器输入“localhost:8081”,启动网址,会发现一个
问题,访问一个接口时,比如 user 查看所有用户,会自动跳转到“login”。当请求一
个地址的时候,发现不是可忽略的地址,会自动拦截,跳转到登录界面,这个登录界面
是基于表单。
这时会要求输入用户账号和密码,用户账号和密码是定义死的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H7xloPdW-1667549379432)(https://cdn.jsdelivr.net/gh/WaterMoonMirror/typora-img/img/202211041526260.png)]
为我之已经测试过了,点击登录,“Users/gerAll”就可以访问了
如上图所示,出现了 3 个账号和密码,这 3 个账号全部返回出来了。当然这里还有
别的接口,“GetById”
测试一下,输入“GetById/1”,返回 ID 为 1 的账号和密码:
五、Java 面试题
1.本质:URL,拦截请求,验证,放行或者拒绝
注意规则的顺序,正常的项目,会有一个访问,并且有拦截请求操作,安全机制本
质上是拦截请求,基于 URL 规则,判断请求是不是要拦截,验证,然后放行或者拒绝。
验证过程,可以调用缓存或数据库实现安全验证规则。
其他的 Java 面试题这节课就不一一说明了,留给大家课后思考。
-
Java Spring Security 安全机制;
-
如何扩展使用 Token 令牌验证;
-
JWT 开源安全令牌组件;
-
如何支持 X509 正式验证;
-
自定义实现 Spring Boot 2.5.x 身份验证;
-
API 安全如何实现;
-
SSO 单点登录怎么实现?
-
微服务 Spring Cloud 安全体系;
证规则。
其他的 Java 面试题这节课就不一一说明了,留给大家课后思考。 -
Java Spring Security 安全机制;
-
如何扩展使用 Token 令牌验证;
-
JWT 开源安全令牌组件;
-
如何支持 X509 正式验证;
-
自定义实现 Spring Boot 2.5.x 身份验证;
-
API 安全如何实现;
-
SSO 单点登录怎么实现?
-
微服务 Spring Cloud 安全体系;
-
转 Java,跳槽一线互联网公司。
Cookie/Session的机制与安全
Cookie和Session是为了在无状态的HTTP协议之上维护会话状态,使得服务器可以知道当前是和哪个客户在打交道。本文来详细讨论Cookie和Session的实现机制,以及其中涉及的安全问题。
因为HTTP协议是无状态的,即每次用户请求到达服务器时,HTTP服务器并不知道这个用户是谁、是否登录过等。现在的服务器之所以知道我们是否已经登录,是因为服务器在登录时设置了浏览器的Cookie!Session则是借由Cookie而实现的更高层的服务器与浏览器之间的会话。
Cookie是由网景公司的前雇员Lou Montulli在1993年发明的,现今Cookie已经广泛使用了。
Cookie 的实现机制
Cookie是由客户端保存的小型文本文件,其内容为一系列的键值对。 Cookie是由HTTP服务器设置的,保存在浏览器中, 在用户访问其他页面时,会在HTTP请求中附上该服务器之前设置的Cookie。 Cookie的实现标准定义在RFC2109: HTTP State Management Mechanism中。 那么Cookie是怎样工作的呢?下面给出整个Cookie的传递流程:
- 浏览器向某个URL发起HTTP请求(可以是任何请求,比如GET一个页面、POST一个登录表单等)
-
对应的服务器收到该HTTP请求,并计算应当返回给浏览器的HTTP响应。
HTTP响应包括请求头和请求体两部分,可以参见:读 HTTP 协议。
-
在响应头加入
Set-Cookie
字段,它的值是要设置的Cookie。在RFC2109 6.3 Implementation Limits中提到: UserAgent(浏览器就是一种用户代理)至少应支持300项Cookie, 每项至少应支持到4096字节,每个域名至少支持20项Cookie。
- 浏览器收到来自服务器的HTTP响应。
-
浏览器在响应头中发现
Set-Cookie
字段,就会将该字段的值保存在内存或者硬盘中。Set-Cookie
字段的值可以是很多项Cookie,每一项都可以指定过期时间Expires
。 默认的过期时间是用户关闭浏览器时。 -
浏览器下次给该服务器发送HTTP请求时, 会将服务器设置的Cookie附加在HTTP请求的头字段
Cookie
中。浏览器可以存储多个域名下的Cookie,但只发送当前请求的域名曾经指定的Cookie, 这个域名也可以在
Set-Cookie
字段中指定)。 -
服务器收到这个HTTP请求,发现请求头中有
Cookie
字段, 便知道之前就和这个用户打过交道了。 - 过期的Cookie会被浏览器删除。
总之,服务器通过Set-Cookie
响应头字段来指示浏览器保存Cookie, 浏览器通过Cookie
请求头字段来告诉服务器之前的状态。 Cookie中包含若干个键值对,每个键值对可以设置过期时间。
Cookie 的安全隐患
Cookie提供了一种手段使得HTTP请求可以附加当前状态, 现今的网站也是靠Cookie来标识用户的登录状态的:
- 用户提交用户名和密码的表单,这通常是一个POST HTTP请求。
- 服务器验证用户名与密码,如果合法则返回200(OK)并设置
Set-Cookie
为authed=true
。 - 浏览器存储该Cookie。
- 浏览器发送请求时,设置
Cookie
字段为authed=true
。 - 服务器收到第二次请求,从
Cookie
字段得知该用户已经登录。 按照已登录用户的权限来处理此次请求。
这里面的问题在哪里?
我们知道可以发送HTTP请求的不只是浏览器,很多HTTP客户端软件(包括curl、Node.js)都可以发送任意的HTTP请求,可以设置任何头字段。 假如我们直接设置Cookie
字段为authed=true
并发送该HTTP请求, 服务器岂不是被欺骗了?这种攻击非常容易,Cookie是可以被篡改的!
Cookie 防篡改机制
服务器可以为每个Cookie项生成签名,由于用户篡改Cookie后无法生成对应的签名, 服务器便可以得知用户对Cookie进行了篡改。一个简单的校验过程可能是这样的:
- 在服务器中配置一个不为人知的字符串(我们叫它Secret),比如:
x$sfz32
。 - 当服务器需要设置Cookie时(比如
authed=false
),不仅设置authed
的值为false
, 在值的后面进一步设置一个签名,最终设置的Cookie是authed=false|6hTiBl7lVpd1P
。 - 签名
6hTiBl7lVpd1P
是这样生成的:Hash(‘x$sfz32‘+‘true‘)
。 要设置的值与Secret相加再取哈希。 - 用户收到HTTP响应并发现头字段
Set-Cookie: authed=false|6hTiBl7lVpd1P
。 - 用户在发送HTTP请求时,篡改了
authed
值,设置头字段Cookie: authed=true|???
。 因为用户不知道Secret,无法生成签名,只能随便填一个。 - 服务器收到HTTP请求,发现
Cookie: authed=true|???
。服务器开始进行校验:Hash(‘true‘+‘x$sfz32‘)
,便会发现用户提供的签名不正确。
通过给Cookie添加签名,使得服务器得以知道Cookie被篡改。然而故事并未结束。
因为Cookie是明文传输的, 只要服务器设置过一次authed=true|xxxx
我不就知道true
的签名是xxxx
了么, 以后就可以用这个签名来欺骗服务器了。因此Cookie中最好不要放敏感数据。 一般来讲Cookie中只会放一个Session Id,而Session存储在服务器端。
Session 的实现机制
Session 是存储在服务器端的,避免了在客户端Cookie中存储敏感数据。 Session 可以存储在HTTP服务器的内存中,也可以存在内存数据库(如redis)中, 对于重量级的应用甚至可以存储在数据库中。
我们以存储在redis中的Session为例,还是考察如何验证用户登录状态的问题。
- 用户提交包含用户名和密码的表单,发送HTTP请求。
- 服务器验证用户发来的用户名密码。
-
如果正确则把当前用户名(通常是用户对象)存储到redis中,并生成它在redis中的ID。
这个ID称为Session ID,通过Session ID可以从Redis中取出对应的用户对象, 敏感数据(比如
authed=true
)都存储在这个用户对象中。 - 设置Cookie为
sessionId=xxxxxx|checksum
并发送HTTP响应, 仍然为每一项Cookie都设置签名。 - 用户收到HTTP响应后,便看不到任何敏感数据了。在此后的请求中发送该Cookie给服务器。
- 服务器收到此后的HTTP请求后,发现Cookie中有SessionID,进行放篡改验证。
- 如果通过了验证,根据该ID从Redis中取出对应的用户对象, 查看该对象的状态并继续执行业务逻辑。
Web应用框架都会实现上述过程,在Web应用中可以直接获得当前用户。 相当于在HTTP协议之上,通过Cookie实现了持久的会话。这个会话便称为Session。
转载请注明来源: http://harttle.com/2015/08/10/cookie-session.html
以上是关于7. Spring Boot2.5 安全机制与 REST API 身份验证实战的主要内容,如果未能解决你的问题,请参考以下文章
全网最新Spring Boot2.5.1整合Activiti5.22.0企业实战教程<流程挂起与激活篇>
全网最新Spring Boot2.5.1整合Activiti5.22.0企业实战教程<UEL表达式篇>
全网最新Spring Boot2.5.1整合Activiti5.22.0企业实战教程<网关篇>
全网最新Spring Boot2.5.1整合Activiti5.22.0企业实战教程<基础篇>