系列文章目录
第一章 基础知识、数据类型学习
第二章 万年历项目
第三章 代码逻辑训练习题
第四章 方法、数组学习
第五章 图书管理系统项目
第六章 面向对象编程:封装、继承、多态学习
第七章 封装继承多态习题
第八章 常用类、包装类、异常处理机制学习
第九章 集合学习
第十章 IO流、多线程学习
第十一章 仓库管理系统JavaSE项目
第十二章 员工管理系统、多表查询、反射实现DBHelper学习
第十三章 DML、DDL、数据库对象学习
第十四章 网络编程、各种标签、CSS学习
第十五章 ECMAScript、BOM学习
第十六章 DOM、jQuery学习
第十七章 servlet、jsp、Cookie、Ajax学习
第十八章 融资管理系统JavaWeb项目
第十九章 MyBatis框架学习
第二十章 逆向工程、Spring框架IOC、AOP学习
第二十一章 SpringMVC框架学习
第二十二章 SpringBoot框架学习
第二十三章 招聘网站框架项目
第二十四章 Vue介绍、窗体内操作、窗体间操作学习
第二十六章 Vue路由配置、网络请求访问框架项目、element组件介绍学习
第二十五章 标准管理系统Vue项目
第二十六章 Linux安装、Nginx反向代理、负载均衡学习
第二十七章 Docker学习
第二十八章 Jenkins学习
第二十九章 Nexus学习
第三十章 Spring Security学习
文章目录
- 系列文章目录
- 前言
- [一、Spring Security介绍](#一、Spring Security介绍)
-
- [1. Spring Security介绍](#1. Spring Security介绍)
- [2. Spring Security特性](#2. Spring Security特性)
- [二、Spring Security代码编写:第一阶段](#二、Spring Security代码编写:第一阶段)
-
- [1. 创建Maven项目](#1. 创建Maven项目)
- [2. 在pom文件里添加依赖](#2. 在pom文件里添加依赖)
- [3. 目录结构](#3. 目录结构)
- [4. SecurityController文件](#4. SecurityController文件)
- [5. 配置SpringBootMain文件](#5. 配置SpringBootMain文件)
- [6. application.yml文件](#6. application.yml文件)
- [7. main.html文件](#7. main.html文件)
- [8. 启动项目](#8. 启动项目)
- [三、Spring Security代码编写:第二阶段](#三、Spring Security代码编写:第二阶段)
-
- [1. 第二阶段第三阶段总体结构图](#1. 第二阶段第三阶段总体结构图)
- [2. 在pom文件里添加依赖](#2. 在pom文件里添加依赖)
- [3. SecurityConfig文件](#3. SecurityConfig文件)
- [4. UserDetailsServiceImpl文件](#4. UserDetailsServiceImpl文件)
- [5. login.html文件](#5. login.html文件)
- [6. 实现效果](#6. 实现效果)
- [四、Spring Security代码编写:第三阶段](#四、Spring Security代码编写:第三阶段)
-
- [1. RememberMeConfig文件](#1. RememberMeConfig文件)
- [2. SecurityConfig文件](#2. SecurityConfig文件)
- [3. login.html更改](#3. login.html更改)
- [4. 创建数据库和表](#4. 创建数据库和表)
- [5. 实现效果](#5. 实现效果)
- [五、Spring Security代码编写:第四阶段](#五、Spring Security代码编写:第四阶段)
-
- [1. 项目结构](#1. 项目结构)
- [2. 在pom文件里添加依赖](#2. 在pom文件里添加依赖)
- [3. 新增show.html界面](#3. 新增show.html界面)
- [4. 更新UserDetailsServiceImpl文件返回值](#4. 更新UserDetailsServiceImpl文件返回值)
- [5. 实现效果](#5. 实现效果)
- 六、CSRF
- 总结
前言
本文我们要讲述:
Spring Security
在下攸攸太上,是有人类女友的外星来客。
一、Spring Security介绍
1. Spring Security介绍
Spring Security是一个功能强大且灵活的安全框架,用于在Spring应用程序中提供身份验证 、授权、保护和攻击防护等安全功能。它提供了大量的配置选项和扩展机制,使开发者能够轻松地集成和定制应用程序的安全需求。
2. Spring Security特性
身份验证(Authentication):Spring Security提供了多种身份验证机制,包括基于表单、HTTP基本认证、OpenID、LDAP、OAuth等。它还支持自定义身份验证逻辑,可以轻松地集成其他身份验证提供者。
授权(Authorization):Spring Security提供了强大的授权机制,可以根据用户的身份和角色来限制其对资源的访问。它支持基于角色和权限的访问控制,可以在代码和配置中定义细粒度的安全规则。
攻击防护(Attack Protection):Spring Security提供了多种防护机制,用于防范常见的安全威胁,如跨站脚本攻击(XSS)、跨站请求伪造(CSRF)、点击劫持、会话管理等。它使用了各种技术和策略,如CSRF令牌、XSS过滤器、会话管理器等来保护应用程序的安全性。
安全事件和日志(Security Events and Logging):Spring Security提供了丰富的安全事件和日志功能,可以记录和跟踪与安全相关的事件。开发者可以基于这些事件和日志来监控和审计应用程序的安全性,并对可能的安全威胁做出响应。
扩展性和定制化(Extensibility and Customization):Spring Security提供了灵活的配置选项和扩展机制,使开发者能够根据应用程序的特定需求进行定制。开发者可以编写自定义的认证和授权逻辑,实现自定义的安全过滤器和拦截器,以满足应用程序的特定安全需求。
本文将着重介绍身份验证、授权的特性。
二、Spring Security代码编写:第一阶段
1. 创建Maven项目
2. 在pom文件里添加依赖
html
<dependencies>
<!-- SpringBoot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.10.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.10.RELEASE</version>
</dependency>
<!-- Thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.1.10.RELEASE</version>
</dependency>
<!--Spring Security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.1.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<!--json-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
<scope>compile</scope>
</dependency>
</dependencies>
3. 目录结构
4. SecurityController文件
java
@Controller
public class SecurityController {
@RequestMapping("/main")
public String main(){
return "main";
}
}
5. 配置SpringBootMain文件
java
@SpringBootApplication
public class SpringBootMain {
public static void main(String[] args) {
SpringApplication.run(SpringBootMain.class, args);
}
}
6. application.yml文件
java
server:
port: 8181
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password:
url: jdbc:mysql://localhost:3308/security
7. main.html文件
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>main</title>
</head>
<body>
<h1>我是Main页面!我要刺杀老师!喝啊!</h1>
<a href="/logout">退出登录</a>
</body>
</html>
8. 启动项目
打开网页,输入:127.0.0.1:8080
做一次页面点击后,控制台输出密码
我们输入固定的用户名:user与密码:891de0f8-256c-4f74-ba5b-999f25531c82可进行登录,登录后在地址栏可以访问/main页面
没有登录前,会自动跳转到/login页面,因为没有做登录之前,程序不让进行其他操作(第二阶段可改)
我们其实登录都是使用自定义的用户名和密码,于是乎,我们如何自定义用户名、密码呢?且听下回分解
三、Spring Security代码编写:第二阶段
欸!我就是下回诶!
1. 第二阶段第三阶段总体结构图
2. 在pom文件里添加依赖
html
<!-- 4.添加mysql数据库的驱动包依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!-- 3.添加Mybatis 的启动器依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
3. SecurityConfig文件
java
package com.jjy.config;
import com.jjy.service.impl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 表单认证
http.formLogin()
.loginProcessingUrl("/login")
//此处表单不写action属性也可以 //当发现/login时认为是登录,需要执行UserDetailsServiceImpl
.successForwardUrl("/main") //此处是post请求
.loginPage("/login.html");
// url 拦截
http.authorizeRequests()
.antMatchers("/login.html").permitAll() //login.html不需要被认证
.anyRequest().authenticated();//所有的请求都必须被认证。必须登录后才能访问。
//关闭csrf防护
http.csrf().disable();
}
@Bean // 是Bean标签,security框架要求密码必须是加密的处理,
public PasswordEncoder getPwdEncoder(){
return new BCryptPasswordEncoder();
}
}
4. UserDetailsServiceImpl文件
自定义用户名为admin,密码为123
java
package com.jjy.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 1. 查询数据库判断用户名是否存在,如果不存在抛出UsernameNotFoundException
if (!username.equals("admin")){
throw new UsernameNotFoundException("用户名不存在");
}
// 把查询出来的密码进行解析,或者直接把password放到构造方法中
String password = passwordEncoder.encode("123");
return new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
5. login.html文件
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
6. 实现效果
四、Spring Security代码编写:第三阶段
记忆功能实现
1. RememberMeConfig文件
java
package com.jjy.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.sql.DataSource;
@Configuration
public class RememberMeConfig {
@Autowired
private DataSource dataSource;
@Bean
public PersistentTokenRepository getPersistentTokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl=new JdbcTokenRepositoryImpl();
jdbcTokenRepositoryImpl.setDataSource(dataSource);
//自动建表,第一次启动时需要,第二次启动时注释掉
//jdbcTokenRepositoryImpl.setCreateTableOnStartup(true); //该代码不好用,使用sql手动创建库,表
return jdbcTokenRepositoryImpl;
}
}
2. SecurityConfig文件
java
package com.jjy.config;
import com.jjy.service.impl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
PersistentTokenRepository repository;
// private RememberMeConfig repository;
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.rememberMe()
.userDetailsService(userDetailsService) //登录逻辑交给哪个对象
.tokenRepository(repository); //持久层对象
// 表单认证
http.formLogin()
.loginProcessingUrl("/login")
//此处表单不写action属性也可以 //当发现/login时认为是登录,需要执行UserDetailsServiceImpl
.successForwardUrl("/main") //此处是post请求
.loginPage("/login.html");
// url 拦截
http.authorizeRequests()
.antMatchers("/login.html").permitAll() //login.html不需要被认证
.anyRequest().authenticated();//所有的请求都必须被认证。必须登录后才能访问。
//关闭csrf防护
http.csrf().disable();
}
@Bean // 是Bean标签,security框架要求密码必须是加密的处理,
public PasswordEncoder getPwdEncoder(){
return new BCryptPasswordEncoder();
}
}
3. login.html更改
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
<input type="checkbox" name="remember-me" value="true"/>记住我 <br/>
<input type="submit" value="提交">
</form>
</body>
</html>
4. 创建数据库和表
创建security数据库
创建表的语句
sql
create table persistent_logins (
username varchar(64) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null)
5. 实现效果
输入如下属性,点击记住我(密码123),之后提交
可以自动跳转页面,同时数据库新增一条数据
点击退出登录后,数据库内数据被清除
五、Spring Security代码编写:第四阶段
本阶段主要做权限验证
1. 项目结构
2. 在pom文件里添加依赖
html
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
3. 新增show.html界面
html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>获得springsequraty属性</h1>
用户名:<span sec:authentication="name">123</span><br/>
用户名:<span sec:authentication="principal.username">456</span><br/>
凭证:<span sec:authentication="credentials">456</span><br/>
权限和角色:<span sec:authentication="authorities">456</span><br/>
客户端地址:<span sec:authentication="details.remoteAddress">456</span><br/>
sessionId:<span sec:authentication="details.sessionId">456</span><br/>
通过权限判断:
<button sec:authorize="hasAuthority('/insert')">新增</button>
<button sec:authorize="hasAuthority('/delete')">删除</button>
<button sec:authorize="hasAuthority('/update')">修改</button>
<button sec:authorize="hasAuthority('/select')">查看</button>
<br/>
通过角色判断:
<button sec:authorize="hasRole('abc')">新增</button>
<button sec:authorize="hasRole('abc')">删除</button>
<button sec:authorize="hasRole('abc')">修改</button>
<button sec:authorize="hasRole('abc1')">查看</button>
</body>
</html>
4. 更新UserDetailsServiceImpl文件返回值
java
return new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,/select,/insert,ROLE_abc1"));
赋予admin用户select、insert的权限,归于ROLE_abc1组下
5. 实现效果
登录后,我们通过地址栏输入http://127.0.0.1:8181/show进入show页面,可以发现,用户admin的权限只有新增、查看两项。
六、CSRF
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种常见的网络攻击技术,攻击者通过伪造用户的请求来实现非法操作,利用用户在目标网站上的身份和权限。
CSRF攻击通常发生在存在用户身份验证的应用程序中。攻击者诱使受害者在已经登录过的网站上执行恶意操作,从而利用受害者的权限进行非法操作。攻击者可以通过各种手段,如发送伪造的电子邮件、社交工程攻击、恶意广告等来引诱受害者点击恶意链接或访问恶意网站。
Spring Security是一个功能强大的安全框架,提供了多种功能来保护应用程序免受常见的安全威胁,包括 CSRF攻击。在Spring Security中,默认情况下启用了CSRF防护。
CSRF防护是通过生成和验证一个CSRF令牌来实现的。这个令牌通常是一个随机生成的字符串,由服务器在用户访问页面时生成,并将其附加到表单或请求的头部中。在用户提交请求时,服务器会验证请求中的令牌是否与服务器生成的令牌匹配,如果不匹配,服务器将拒绝该请求,防止CSRF攻击的发生。
在Spring Security配置中,可以使用csrf()方法来配置和启用CSRF防护。默认情况下,Spring Security会生成一个CSRF令牌,并将其附加到表单和请求头中。如果需要关闭CSRF防护,可以使用http.csrf().disable()方法来禁用它。
总结起来,CSRF是一种常见的网络攻击技术,Spring Security提供了默认的CSRF防护来保护应用程序免受此类攻击。
总结
本文讲述了:
Spring Security:进行身份验证、授权功能的框架
在下攸攸太上,如果把我的生活拍成电视剧,那将会是《来自行星的高级生命体》。