Security 原理分析
SpringSecurity 过滤器链
SpringSecurity 采用的是责任链的设计模式,它有一条很长的过滤器链。现在对这条过滤器链的各个进行说明:
pom文件
导入整合项目的依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.kaung.w</groupId>
<artifactId>spring-06-security</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-06-security</name>
<description>security 安保 for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--Thymeleaf依赖开始 当前默认版本3.0.12-->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
<!-- 安全 security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.3.9.RELEASE</version>
</dependency>
<!-- thymeleaf-springSecurity 整合包 -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-
WebAsyncManagerIntegrationFilter:将 Security 上下文与 Spring Web 中用于处理异步请求映射的 WebAsyncManager 进行集成。
-
SecurityContextPersistenceFilter:在每次请求处理之前将该请求相关的安全上下文信息加载到 SecurityContextHolder 中,然后在该次请求处理完成之后,将 SecurityContextHolder 中关于这次请求的信息存储到一个“仓储”中,然后将 SecurityContextHolder 中的信息清除,例如在Session中维护一个用户的安全信息就是这个过滤器处理的。
-
HeaderWriterFilter:用于将头信息加入响应中。
-
CsrfFilter:用于处理跨站请求伪造。
-
LogoutFilter:用于处理退出登录。
-
UsernamePasswordAuthenticationFilter:用于处理基于表单的登录请求,从表单中获取用户名和密码。默认情况下处理来自 /login 的请求。从表单中获取用户名和密码时,默认使用的表单 name 值为 username 和 password,这两个值可以通过设置这个过滤器的usernameParameter 和 passwordParameter 两个参数的值进行修改。
-
DefaultLoginPageGeneratingFilter:如果没有配置登录页面,那系统初始化时就会配置这个过滤器,并且用于在需要进行登录时生成一个登录表单页面。
-
BasicAuthenticationFilter:检测和处理 http basic 认证。
-
RequestCacheAwareFilter:用来处理请求的缓存。
-
SecurityContextHolderAwareRequestFilter:主要是包装请求对象request。
-
AnonymousAuthenticationFilter:检测 SecurityContextHolder 中是否存在 Authentication 对象,如果不存在为其提供一个匿名 Authentication。
-
SessionManagementFilter:管理 session 的过滤器
-
ExceptionTranslationFilter:处理 AccessDeniedException 和 AuthenticationException 异常。
-
FilterSecurityInterceptor:可以看做过滤器链的出口。
-
RememberMeAuthenticationFilter:当用户没有登录而直接访问资源时, 从 cookie 里找出用户的信息, 如果 Spring Security 能够识别出用户提供的remember me cookie, 用户将不必填写用户名和密码, 而是直接登录进入系统,该过滤器默认不开启。
启用security的实体类
package com.kaung.w.config;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* @ClassName : MySecurityConfig //类名
* @Description : security安全配置 //描述
* @Author : W //作者
* @Date: 2021/4/29 11:33
* @EnableWebSecurity Aop拦截器
*/
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println ("进入了MySecurityConfig方法!");
/**责任链式编程
* 首页所有人可以访问,功能页只 有对应有权限的人才能访问
* 请求授权的规则
* */
http.authorizeRequests ()
.antMatchers ("/").permitAll ()
.antMatchers ("/level1/**").hasRole ("vip1")
.antMatchers ("/level2/**").hasRole ("vip2")
.antMatchers ("/level3/**").hasRole ("vip3");
//开启登录的页面 没有权限默认会到登录页面,http.formLogin ()
//定制登录页 loginPage ("/toLogin");
http.formLogin ().loginPage ("/toLogin");
// 开启了注销功能
//防止攻击 springBoot 默认开启了防止网站攻击
//关闭 springboot默认配置
http.csrf ().disable ();
http.logout ().logoutSuccessUrl ("/");
//开启记住我 自定义记住我的name值
http.rememberMe ().rememberMeParameter ("rememberMe");
}
/**
* //认证,springboot 2.1.X可以直接使用
* //密码编码: PasswordEncoder
* //在Spring secutiry 5.0+ 新增了很多的加密方法
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication ().passwordEncoder (new BCryptPasswordEncoder ())
//这些数据正常应该从数据库中读
.withUser ("ww").password (new BCryptPasswordEncoder ().encode ("123")).roles ("vip1", "vip2")
.and ()
.withUser ("root").password (new BCryptPasswordEncoder ().encode ("123")).roles ("vip1", "vip2", "vip3")
.and ()
.withUser ("guest").password (new BCryptPasswordEncoder ().encode ("123456")).roles ("vip2");
}
}
RouterController 配置类
package com.kaung.w.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ClassName : RouterController //类名
* @Description : 页面跳转的配置 controller层 //描述
* @Author : W //作者
* @Date: 2021/4/29 10:48
*/
@Controller
public class RouterController {
@RequestMapping({"/", "/index"})
public String index() {
return "index";
}
@RequestMapping({"/toLogin"})
public String toLogin() {
return "views/login";
}
@RequestMapping({"/level1/{id}"})
public String toLevel1(@PathVariable("id") int id) {
return "views/level1/" + id;
}
@RequestMapping({"/level2/{id}"})
public String toLevel2(@PathVariable("id") int id) {
return "views/level2/" + id;
}
@RequestMapping({"/level3/{id}"})
public String toLevel3(@PathVariable("id") int id) {
return "views/level3/" + id;
}
}
资源图示