千锋教育SpringSecurity框架教程,Spring Security+JWT微服务项目实战教程
https://www.bilibili.com/video/BV1Fd4y1k7rq/?p=3&spm_id_from=pageDriver&vd_source=0d7b1712ce42c1a2fa54bb4e1d601d78
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
作者:千锋-索尔
版本:QF1.0
版权:千锋Java教研院
一、Spring Security简介
Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。Spring Security致力于为Java应用程序提供身份验证和授权的能力。像所有Spring项目一样,Spring Security的真正强大之处在于它可以轻松扩展以满足定制需求的能力。
Spring Security两大重要核心功能:用户认证(Authentication)和用户授权(Authorization)。
用户认证:验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。
用户授权:验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,有的用户既能读取,又能修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。
二、快速开始
使用Springboot工程搭建Spring Security项目。
1.引入依赖
在pom中新增了Spring Security的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2.创建测试访问接口
用于访问接口时触发Spring Security登陆页面
package com.qf.my.ss.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* web controller
* @author Thor
* @公众号 Java架构栈
*/
3.访问接口,自动跳转至Security登陆页面
访问add接口,讲自动跳转至Security的登陆页面
默认账号是: user
默认密码是:启动项目的控制台中输出的密码
三、Spring Security基础概念
在上一节中访问add接口,发现被Spring Security的登陆页面拦截,可以猜到这是触发了Security框架的过滤器。Spring Security本质上就是一个过滤器链。下面讲介绍Security框架的过滤器链。
1.过滤器链
WebAsyncManagerIntegrationFilter:将SecurityContext集成到Spring MVC中用于管理异步请求处理的WebAsyncManager中。
SecurityContextPersistenceFilter:在当前会话中填充SecurityContext,SecurityContext即Security的上下文对象,里面包含了当前用户的认证及权限信息等。
HeaderWriterFilter:向请求的Header中添加信息
CsrfFilter:用于防止CSRF(跨域请求伪造)攻击。Spring Security会对所有post请求验证是否包含系统生成的CSRF的信息,如果不包含则报错。
LogoutFilter:匹配URL为“/logout”的请求,清除认证信息,实现用户注销功能。
UsernamePasswordAuthenticationFilter:认证操作的过滤器,用于匹配URL为“/login”的POST请求做拦截,校验表单中的用户名和密码。
DefaultLoginPageGeneratingFilter:如果没有配置登陆页面,则生成默认的认证页面
DefaultLogoutPageGeneratingFilter:用于生成默认的退出页面
BasicAuthenticationFilter:用于Http基本认证,自动解析Http请求头中名为Authentication的内容,并获得内容中“basic”开头之后的信息。
RequestCacheAwareFilter:用于缓存HttpServletRequest
SecurityContextHolderAwareRequestFilter:用于封装ServletRequest,让ServletRequest具备更多功能。
AnonymousAuthenticationFilter:对于未登录情况下的处理,当SecurityContextHolder中认证信息为空,则会创建一个匿名用户存入到SecurityContextHolder中
SessionManagementFilter:限制同一用户开启多个会话
ExceptionTranslationFilter:异常过滤器,用来处理在认证授权过程中抛出异常。
FilterSecurityInterceptor:获取授权信息,根据SecurityContextHolder中存储的用户信息判断用户是否有权限访问
2.过滤器加载过程
Springboot在整合Spring Security项目时会自动配置DelegatingFilterProxy过滤器,若非Springboot工程,则需要手动配置该过滤器。
过滤器如何进行加载的?
结合上图和源码,Security在DelegatingFilterProxy的doFilter()调用了initDelegat()方法,在该方法中调用了WebApplicationContext的getBean()方法,该方法出发FilterChainProxy的doFilterInternal方法,用于获取过滤链中的所有过滤器并进行加载。
四、Spring Security的认证方式-基本认证
1.认证概念
所谓的认证,就是用来判断系统中是否存在某用户,并判断该用户的身份是否合法的过程,解决的其实是用户登录的问题。认证的存在,是为了保护系统中的隐私数据与资源,只有合法的用户才可以访问系统中的资源。
2.认证方式
在Spring Security中,常见的认证方式可以分为HTTP层面和表单层面,常见的认证方式如下:
HTTP基本认证
Form表单认证
HTTP摘要认证
3.基本认证
HTTP基本认证是在RFC2616标准中定义的一种认证模式,它以一种很简单的方式与用户进行交互。HTTP基本认证可以分为如下4个步骤:
客户端首先发起一个未携带认证信息的请求;
然后服务器端返回一个401 Unauthorized的响应信息,并在WWW-Authentication头部中说明认证形式:当进行HTTP基本认证时,WWW-Authentication会被设置为Basic realm=“被保护的页面”;
接下来客户端会收到这个401 Unauthorized响应信息,并弹出一个对话框,询问用户名和密码。当用户输入后,客户端会将用户名和密码使用冒号进行拼接并用Base64编码,然后将其放入到请求的Authorization头部并发送给服务器;
最后服务器端对客户端发来的信息进行解码得到用户名和密码,并对该信息进行校验判断是否正确,最终给客户端返回响应内容。
HTTP基本认证是一种无状态的认证方式,与表单认证相比,HTTP基本认证是一种基于HTTP层面的认证方式,无法携带Session信息,也就无法实现Remember-Me功能。另外,用户名和密码在传递时仅做了一次简单的Base64编码,几乎等同于以明文传输,极易被进行密码窃听和重放攻击。所以在实际开发中,很少会使用这种认证方式来进行安全校验。
基本认证的代码实现:
-
创建SecurityConfig配置类
package com.qf.my.ss.demo.config;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* @author Thor
* @公众号 Java架构栈
*/
-
Basic认证详解
在未登录状态下访问目标资源时,查看响应头,可以看到WWW-Authenticate认证信息:WWW-Authenticate:Basic realm="Realm",其中WWW-Authenticate: 表示服务器告知浏览器进行代理认证工作。Basic: 表示认证类型为Basic认证。realm="Realm": 表示认证域名为Realm域。
根据401和以上响应头信息,浏览器会弹出一个对话框,要求输入 用户名/密码,Basic认证会将其拼接成 “用户名:密码” 格式,中间是一个冒号,并利用Base64编码成加密字符串xxx;然后在请求头中附加 Authorization: Basic xxx 信息,发送给后台认证;后台需要利用Base64来进行解码xxx,得到用户名和密码,再校验 用户名:密码 信息。如果认证错误,浏览器会保持弹框;如果认证成功,浏览器会缓存有效的Base64编码,在之后的请求中,浏览器都会在请求头中添加该有效编码。
五、Form表单认证
在SpringBoot开发环境中,只要我们添加了Spring Security的依赖包,就会自动实现表单认证。可以通过WebSecurityConfigurerAdapter提供的configure方法看到默认的认证方式就是表单认证
protected void configure(HttpSecurity http) throws Exception {
logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().and()
.httpBasic();
}
1.表单认证中的预置url和页面
默认的formLogin配置中,自动配置了一些url和页面:
/login(get): get请求时会跳转到这个页面,只要我们访问任意一个需要认证的请求时,都会跳转到这个登录界面。
/login(post): post请求时会触发这个接口,在登录页面点击登录时,默认的登录页面表单中的action就是关联这个login接口。
/login?error: 当用户名或密码错误时,会跳转到该页面。
/: 登录成功后,默认跳转到该页面,如果配置了index.html页面,则 ”/“ 会重定向到index.html页面,当然这个页面要由我们自己实现。
/logout: 注销页面。
/login?logout: 注销成功后跳转到的页面。
由此可见,SpringSecurity默认有两个login,即登录页面和登录接口的地址都是 /login:
如果是 GET 请求,表示你想访问登录页面;如果是 POST 请求,表示你想提交登录数据。 对于这几个URL接口,我们简单了解即可。
2.自定义认证页面
-
自定义登陆页面