前言:
小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java半年多时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师。
这个SpringBoot基础学习系列用来记录我学习SpringBoot框架基础知识的全过程 (这个系列是参照B站狂神的SpringBoot最新教程来写的,由于是之前整理的,但当时没有发布出来,所以有些地方可能有错误,希望大家能够及时指正!)
之后我将会以一天一更的速度更新这个系列,还没有学习SpringBoot的小伙伴可以参照我的博客学习一下;当然学习过的小伙伴,也可以顺便跟我一起复习一下基础。
最后,希望能够和大家一同进步吧!加油吧!少年们!
7. 整合SpringSercurity框架 7.1 SpringSercurity初步认识 7.1.1 安全问题思考 1.安全是否重要?废话不多说,让我们开始今天的学习内容吧,由于今天我们来到了SpringBoot基础学习的第九站:整合SpringSercurity框架!
2.通常使用哪些简单方式来保证安全?很重要,在Web网站开发中,安全应该第一位
3.安全属于功能性需求吗?例如我们会经常使用的过滤器和拦截器等手段,来对未通过用户身份的人进行拦截和过滤,避免出现非法登录登情况,避免造成网站的信息泄露和财产损失
4.安全应该在什么时候考虑?安全属于非功能性需求,因为安全只是为了保证网站的用户信息的安全性,并非我们Web网站的核心业务功能
做网站的时候,安全应该设计之初就考虑
- 如果网站的系统存在漏洞,可能会出现隐私泄露问题
- 架构一旦确定,再去修改就很难了,可能需要修改大量代码
7.1.2 SpringSecurity基本概念 1.SpringSecurity官方解释使用SpringSecurity和Shrio等框架技术
原文:
Spring Security is a powerful and highly customizable (可定制化) authentication (验证) and access-control (权限控制) framework. It is the de-facto (实际上) standard for securing Spring-based applications.
译文:
Spring Security 是一个功能强大并且可高度定制化的身份验证和权限控制框架,它实际上是一个保护Spring基础应用的标准
原文:
Spring Security is a framework that focuses on providing both authentication (身份验证) and authorization (授权) to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements
译文:
Spring Sercurity 是一个专注于为Java应用程序、提供身份验证和授权的框架。与所有的Spring项目一样,Spring Sercurity的真正强大之处是,可以很容易地去扩展它来满足定制需求
2.Spring Security简介简介:
Spring Sercurity是针对Spring项目的安全框架,也是Spring Boot底层安全模块的技术选型,它可以实现强大的Web安全控制,对于安全控制,我们仅需要引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理
记住几个类:
- WebSercurityConfigurerAdapter:Web安全配置适配器,即自定义Sercurity策略
- AuthenticationMangerBuilder:验证管理修筑器,即自定义认证策略
- @EnableWebSecurity:开启WebSecurity模式
Spring Sercurity的两个主要目标是 “认证” 和 “授权” (访问控制),“认证” (Authentication) “授权” (Authorization) 这个概念是通用的,而不是只在 Spring Security 中存在
总结:
- Spring Sercurity是一个提供认证和授权的可高定制化的安全框架
- 核心是把权限赋给角色,而不是赋给具体的用户
- 用户只需要通过获取角色就能够获取相应的权限
-
它们很像,除了类不一样,名字不一样
-
都具有认证和授权 (不同身份具有不同权限),比如说功能权限、访问权限、菜单权限
-
如果使用拦截器或者过滤器,会有大量的原生代码,导致代码冗余
7.2 搭建项目基本环境 7.2.1 创建Spring Boot应用 1.创建Spring Initializr项目 2.设置项目基本信息 3.选择项目资源依赖 4.选择项目存放位置 5.项目创建成功 6.删除多余项目文件 7.2.2 引入资源依赖和编写配置文件 1.引入相关资源依赖从MVC到SSH,再到SSM,到现如今的Spring Boot,不仅体现框架思想的重要性,同时也体现AOP的思想,使用横切,自定义配置类
- 引入spring security的资源依赖
org.springframework.boot spring-boot-starter-security
- 引入thymeleaf资源依赖
org.thymeleaf thymeleaf-spring5 org.thymeleaf.extras thymeleaf-extras-java8time
- 引入security-thymeleaf整合资源依赖
org.thymeleaf.extras thymeleaf-extras-springsecurity5 3.0.4.RELEASE
- 查看资源是否正确导入
- 引入所有相关资源依赖后的pom.xml配置文件
2.编写核心配置文件4.0.0 org.springframework.boot spring-boot-starter-parent 2.4.5 com.kuang springboot-06-security 0.0.1-SNAPSHOT springboot-06-security Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine org.thymeleaf thymeleaf-spring5 org.thymeleaf.extras thymeleaf-extras-java8time org.thymeleaf.extras thymeleaf-extras-springsecurity5 3.0.4.RELEASE org.springframework.boot spring-boot-maven-plugin
# 修改Tomcat端口号 server.port=8888 # 关闭模板引擎缓存 spring.thymeleaf.cache=false7.2.3 引入相关静态资源 1.项目基本结构 2.编写静态页面
这里只给出index主页和login登录页的代码,该项目的其他静态资源可以去这个链接进行下载:https://gitee.com/ENNRIAAA/spring-security-material
- 编写index.xml
首页
- 编写login.html
登录
登录
注册
blog.kuangstudy.com
Spring Security Study by 秦疆
7.2.4 编写控制器类和页面访问测试
1.编写RouterController控制器类
package com.kuang.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
// 使用@Controller注解,实现Controller接口,托管给Spring容器管理
@Controller
public class RouterController {
// 跳转主页
@RequestMapping({"/","/index"})
public String index() {
return "index";
}
// 跳转登录页
@RequestMapping("/goLogin")
public String toLogin() {
return "views/login";
}
// 跳转level下的页面
@RequestMapping("/goLevel1/{id}")
// 使用@PathVariable注解,将id绑定到请求模板上
public String toLevel1(@PathVariable("id") int id) {
// 使用id遍历level下的多个页面
return "views/level1/"+id;
}
// 跳转level2下的页面
@RequestMapping("/goLevel2/{id}")
public String toLevel2(@PathVariable("id") int id) {
return "views/level2/"+id;
}
// 跳转level3下的页面
@RequestMapping("/goLevel3/{id}")
public String toLevel3(@PathVariable("id") int id) {
return "views/level3/"+id;
}
}
2. 页面访问测试
结果:访问主页成功!
7.3 完善项目基本功能 7.3.1 了解Servlet Application和Java Configuration
1.Servlet Application的使用Spring Security官方文档地址链接:https://docs.spring.io/spring-security/site/docs/5.2.10.RELEASE/reference/html5/
- 如果公司的项目开发还停留在SSM阶段,查看Spring Security官方文档中的Servlet Application相关内容
2.Java Configuration的使用官方文档地址链接:https://docs.spring.io/spring-security/site/docs/5.2.10.RELEASE/reference/html5/#servlet-applications
- 如果使用Spring Boot进行开发,查看Spring Security官方文档中的Java Configuration相关内容
7.3.2 编写自定义SecurityConfig配置类 1.实现授权功能官方文档地址链接:https://docs.spring.io/spring-security/site/docs/5.2.10.RELEASE/reference/html5/#jc
1-1 查看WebSecurityConfigurerAdapter类源码在进行自定义SecurityConfig配置类前,我们首先了解一下WebSecurityConfigurerAdapter类和HttpSecurity类,即Web安全配置适配器的源码和HTTP安全这两个类
// Web安全配置适配器 public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigurer1-2 查看HttpSecurity类源码{ // ...(忽略前面部分代码)... // configure方法,参数为HttpSecurity protected void configure(HttpSecurity http) throws Exception { this.logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity)."); // 如果是http的授权请求,则请求中的任何请求都通过的验证 http.authorizeRequests((requests) -> { ((AuthorizedUrl)requests.anyRequest()).authenticated(); }); // http的登录请求 http.formLogin(); // http的主页请求 http.httpBasic(); } // ...(省略后面部分代码)... }
// HttpSecurity类 public final class HttpSecurity extends AbstractConfiguredSecurityBuilder1-3 编写SecurityConfig安全配置类implements SecurityBuilder , HttpSecurityBuilder { // ...(忽略前面部分代码)... // 如果验证失败,转发请求到登录页面 // 登录验证 public FormLoginConfigurer formLogin() throws Exception { return getOrApply(new FormLoginConfigurer<>()); } // ...(省略后面部分代码)... }
package com.kuang.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.WebSecurityConfiguration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
//继承WebSecurityConfigurerAdapter类(Web安全配置适配器),自定义Security策略
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//首页所有人可以访问,功能页只有对应权限的人才能访问
//请求授权(责任链模式),匹配相关的页面和角色
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/level1
@EnableWebSecurity
//继承WebSecurityConfigurerAdapter类(Web安全配置适配器),自定义Security策略
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 首页所有人可以访问,功能页只有对应权限的人才能访问
// 请求授权(责任链模式),匹配相关的页面和角色
http.authorizeRequests()
// 如果匹配到"/"请求,允许所有角色访问
.antMatchers("/").permitAll()
// 如果匹配到"/level1
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 这些数据正常应该从数据库中读取
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
// user01用户,拥有角色"user"的权限
.withUser("user01").password(new BCryptPasswordEncoder().encode("123456")).roles("user")
// 使用and连接多个用户的认证设置
// admin01用户,拥有角色"user'、"vip"和"admin"的权限
.and()
.withUser("admin01").password(new BCryptPasswordEncoder().encode("123456")).roles("user","vip","admin")
.and()
// user02用户,拥有角色"user"和"vip的权限
.withUser("user02").password(new BCryptPasswordEncoder().encode("123456")).roles("user","vip");
}
}
2-2 与数据库连接实现认证
- 如果要连接数据库进行进行认证,需要使用Spring Security中的JDBC Authentication
官网地址:https://docs.spring.io/spring-security/site/docs/5.2.10.RELEASE/reference/html5/#jc-authentication-jdbc
// 自动装配数据源
@Autowired
private DataSource dataSource;
// 自动装配全局配置
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// 确保密码是被正确编码的
UserBuilder users = User.withDefaultPasswordEncoder();
auth
// JDBC认证
.jdbcAuthentication()
// 数据源
.dataSource(dataSource)
// 默认的数据库
.withDefaultSchema()
// 表中的普通用户名,密码和角色
.withUser(users.username("user").password("password").roles("USER"))
// 表中的管理员用户名,密码和角色
.withUser(users.username("admin").password("password").roles("USER","ADMIN"));
}
3.用户权限测试
3-1 使用admin01用户进行权限测试
admin01用户具有管理员、VIP和普通用户的权限,因此它应该可以访问所有页面;为了进行验证,我们分别选取level1、level2和level3下的1、2、3页面进行访问测试
- 使用admin01账户进行登录
- 访问level1下的1页面
结果:访问成功!
- 访问leve2下的2页面
结果:=访问成功!
- 访问level3下的3页面
结果:访问成功!
总结:
3-2 使用user01用户进行权限测试使用admin01用户登录后,可以访问所有的页面,与我们预期结果相同
由于user01用户只具有普通用户的权限,因此它应该只能访问level3下的所有页面;为了进行验证,我们分别选取level1、level2和level3下的1、2、3页面进行访问测试
- 使用user01用户进行登录
- 访问level1下的1页面
结果:访问失败,出现403禁止访问提示!
- 访问leve2下的2页面
结果:访问失败,出现403禁止访问提示!
- 访问level3下的3页面
结果:访问成功!
总结:
3-3 使用user02用户进行权限测试与我们的预期相同,user01只能访问level3下的所有页面,而level1和level2下的页面禁止访问!
由于user02用户具有普通用户和VIP的权限,因此它应该能够访问level2和level3下的所有页面,为了进行验证,我们分别选取level1、level2和level3下的1、2、3页面进行访问测
- 使用user02用户进行登录
- 访问level1下的1页面
结果:访问失败,出现403禁止访问提示!
- 访问leve2下的2页面
结果:访问成功!
- 访问level3下的3页面
结果:访问成功!
总结:
7.3.3 实现注销功能 1.查看logout方法源码与我们的预期相同,user02能够访问level2和level3下的所有页面,而level1下的页面禁止访问!
- 查看HttpSecurity类中logout方法源码
// HttpSecurity类 public final class HttpSecurity extends AbstractConfiguredSecurityBuilderimplements SecurityBuilder , HttpSecurityBuilder { // 用户注销 public LogoutConfigurer logout() throws Exception { return getOrApply(new LogoutConfigurer<>()); }
-
源码中对logout相关参数的介绍
如果要设置注销成功后跳转到首页,可以使用logoutSuccessUrl,设置退出成功请求"/",退出后跳转到主页;
使用deletecookie,设置其值为"remove",表示移除cookie;
使用invalidateHttpSession,设置其值为false,表示销毁Session;
// 设置退出登录的请求和退出登录成功的请求
http.logout().logoutUrl("/custom-logout").logoutSuccessUrl("/logout-success")
// 设置移除cookie和销毁Session
.deletecookies("remove").invalidateHttpSession(false);
2.编写SecurityConfig实现注销功能
- 修改SecurityConfig类的configure方法实现注销功能
package com.kuang.config;
import com.sun.org.apache.xpath.internal.operations.And;
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.WebSecurityConfiguration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@EnableWebSecurity
// 继承WebSecurityConfigurerAdapter类(Web安全配置适配器),自定义Security策略
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// 如果匹配到"/"请求,允许所有角色访问
.antMatchers("/").permitAll()
// 如果匹配到"/level1
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//...(省略后面部分代码)...
}
}
3.改进注销功能
3-1 CSRF跨站请求伪造
3-2 修改SecurityConfig类CSRF(cross site request forgery),跨站请求伪造,也称"One Click Attack"或者Session Riding,通过编写为CSRF或者XSRF,是一种对网站的恶意利用
package com.kuang.config;
import com.sun.org.apache.xpath.internal.operations.And;
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.WebSecurityConfiguration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@EnableWebSecurity
// 继承WebSecurityConfigurerAdapter类(Web安全配置适配器),自定义Security策略
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// 如果匹配到"/"请求,允许所有角色访问
.antMatchers("/").permitAll()
// 如果匹配到"/level1
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//...(省略后面部分代码)...
}
}
4.修改主页和访问测试
4-1 修改indx.html主页
首页
Spring Security Study by 秦疆
4-2 访问主页
4-3 注销登录
4-4 跳转登录页
7.3.4 自定义登录页和记住我
1.登录相关参数介绍
http.authorizeRequests().antMatchers("
@EnableWebSecurity
// 继承WebSecurityConfigurerAdapter类(Web安全配置适配器),自定义Security策略
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// 如果匹配到"/"请求,允许所有角色访问
.antMatchers("/").permitAll()
// 如果匹配到"/level1
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//...(省略后面部分代码)...
}
}
3.修改登录页和主页
3-1 修改登录页
登录
登录
注册
blog.kuangstudy.com
Spring Security Study by 秦疆
3-2 修改主页
首页
Spring Security Study by 秦疆
4.页面访问测试
4-1 使用admin01登录访问主页
4-2 使用user01登录访问主页
4-3 使用user02登录访问主页
好了,今天的有关 SpringBoot基础学习之整合SpringSercurity框架 的学习就到此结束啦,欢迎小伙伴们积极学习和讨论,喜欢的可以给蜗牛君点个关注,顺便来个一键三连,我们下期见,拜拜啦!
参考视频链接:https://www.bilibili.com/video/BV1PE411i7CV(【狂神说Java】SpringBoot最新教程IDEA版通俗易懂)



