安全框架
● Apache Shiro
● Spring Security
● 自研:Filter
权限模型
1.RBAC(Role Based Access Controll)
- 用户(t_user)
- id,username,password,xxx
- 1,zhangsan
- 2,lisi
- 用户_角色(t_user_role)【N 对 N 关系需要中间表】
- zhangsan, admin
- zhangsan,common_user
- lisi, hr
- lisi, common_user
- 角色(t_role)
- id,role_name
- admin
- hr
- common_user
- 角色_权限(t_role_perm)
- admin, 文件r
- admin, 文件w
- admin, 文件执行
- admin, 订单query,create,xxx
- hr, 文件r
- 权限(t_permission)
- id,perm_id
- 文件 r,w,x
- 订单 query,create,xxx
2.ACL(Access Controll List)
- 用户(t_user)
- zhangsan
- lisi
- 用户_权限(t_user_perm)
- zhangsan,文件 r
- zhangsan,文件 x
- zhangsan,订单 query
- 权限(t_permission)
- id,perm_id
- 文件 r,w,x
- 订单 query,create,xxx
安全架构
1.认证:Authentication
who are you?
登录系统,用户系统
2.授权:Authorization
what are you allowed to do?
权限管理,用户授权
3.攻击防护
● XSS(Cross-site scripting)——跨站脚本攻击
● CSRF(Cross-site request forgery)——跨站请求伪造
● CORS(Cross-Origin Resource Sharing)——跨域资源共享攻击
● SQL 注入
● …
Spring Security 原理
1.过滤器链架构
Spring Security 利用 FilterChainProxy 封装一系列拦截器链,实现各种安全拦截功能
Servlet三大组件:Servlet、Filter、Listener
2.FilterChainProxy
3.SecurityFilterChain
实战
新建项目-boot3-13-security
新建模块
boot3-13-security创建模块
| 项 | 值 |
|---|---|
| 名称 | boot3-13-security |
| 位置 | D:\Study-Java\2023\SpringBoot3-Study |
| 语言 | Java |
| 构建系统 | Maven |
| JDK | 版本:17 供应商:Eclipse Temurin(AdoptOpenJDK HotSpot)17.0.8 位置:C:\Users\Administrator.jdks\temurin-17.0.8 |
| 主 ID | com.atguigu |
| 工件 ID | boot3-13-security |
| 软件包名称 | com.atguigu.boot3.security |
- SpringBoot
3.2.0 - 依赖项目
Developer Tools-- LombokWeb-- Spring WebTemplate Engines-- ThymeleafSecurity-- Spring Security
资源目录
│ pom.xml│├─src│ ├─main│ │ ├─java│ │ │ └─com│ │ │ └─atguigu│ │ │ └─boot3│ │ │ └─security│ │ │ │ Boot313SecurityApplication.java│ │ │ ││ │ │ ├─cofig│ │ │ │ AppSecurityConfiguration.java│ │ │ ││ │ │ └─controller│ │ │ HelloController.java│ │ │ LoginController.java│ │ ││ │ └─resources│ │ │ application.properties│ │ ││ │ ├─static│ │ └─templates│ │ index.html│ │ login.html
1.引入依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.thymeleaf.extras</groupId><artifactId>thymeleaf-extras-springsecurity6</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-test</artifactId><scope>test</scope></dependency></dependencies>
2.页面
首页-index.html
<h1>Welcome To Spring Security!</h1><a th:href="@{/hello}">hello</a><br /><a th:href="@{/world}">world</a>
登录页-login.html
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"><head><title>Spring Security Example</title></head><body><div th:if="${param.error}">Invalid username and password.</div><div th:if="${param.logout}">You have been logged out.</div><form th:action="@{/login}" method="post"><div><label> User Name : <input type="text" name="username" /> </label></div><div><label> Password: <input type="password" name="password" /> </label></div><div><input type="submit" value="Sign In" /></div></form></body></html>
3.控制器
Login
package com.atguigu.boot3.security.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;@Controllerpublic class LoginController {@GetMapping("/login")public String loginPage() {return "login";}}
Hello
package com.atguigu.boot3.security.controller;import org.springframework.security.access.prepost.PreAuthorize;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HelloController {@GetMapping("/hello")public String hello() {return "Hello Spring Security!";}@PreAuthorize("hasAuthority('world_exec')")@GetMapping("/world")public String world() {return "Hello Spring Security!";}}
4.配置类
package com.atguigu.boot3.security.cofig;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;import org.springframework.security.config.annotation.web.builders.HttpSecurity;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.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.security.provisioning.InMemoryUserDetailsManager;import org.springframework.security.web.SecurityFilterChain;/*** 配置类* 1. 自定义请求授权规则:http.authorizeHttpRequests* 2. 自定义登录规则:http.formLogin* 3. 自定义用户信息查询规则:UserDetailsService* 4. 开启方法级别的精确权限控制:EnableMethodSecurity*/@Configuration@EnableMethodSecuritypublic class AppSecurityConfiguration {/*** 自定义请求授权规则* @param http HttpSecurity* @return 请求授权规则* @throws Exception 异常信息*/@BeanSecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {//请求授权http.authorizeHttpRequests(registry -> {registry.requestMatchers("/").permitAll()//1. 首页无需登录.anyRequest().authenticated();//2. 剩下的任意请求都需要认证(登录)});//表单登录//3. 表单登录功能:开启默认表单登录功能,Spring Security 提供默认登录页http.formLogin(formLogin -> {//自定义登录页位置,并且所有人都能访问formLogin.loginPage("/login").permitAll();});return http.build();}/*** 自定义登录规则* @param passwordEncoder 密码加密器* @return 用户详情信息*/@BeanUserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {//用户信息UserDetails zhangsan = User.withUsername("zhangsan").password(passwordEncoder.encode("123456")).roles("admin", "hr").authorities("file_read", "file_write").build();UserDetails lisi = User.withUsername("lishi").password(passwordEncoder.encode("123456")).roles("hr").authorities("file_read").build();UserDetails wangwu = User.withUsername("wangwu").password(passwordEncoder.encode("123456")).roles("admin").authorities("file_write","world_exec").build();//默认内存中保存所有用户信息InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(zhangsan, lisi, wangwu);return manager;}/*** 密码加密器* @return 密码加密器*/@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}}
5.测试
无权限
Welcome To Spring Security!helloworld
- 点击
world,进入 http://localhost:8080/login
User Name :zhangsanPassword:123456
提示无权限
Whitelabel Error PageThis application has no explicit mapping for /error, so you are seeing this as a fallback.Mon Jan 08 11:57:28 CST 2024There was an unexpected error (type=Forbidden, status=403).
有权限
Welcome To Spring Security!helloworld
- 点击
world,进入 http://localhost:8080/login
User Name :wangwuPassword:123456
有权限
Hello Spring Security!