# springSecurity
**Repository Path**: javawcj/spring-security
## Basic Information
- **Project Name**: springSecurity
- **Description**: 包含 Spring Security 安全框架的基础知识,认证、授权、安全过滤器链等内容,并提供了案例代码和实践练习,方便学习和掌握 Spring Security 的使用方法。
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2023-05-13
- **Last Updated**: 2023-06-02
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# SpringSecurity
在web开发中,安全第一!过滤取、拦截器等
功能性需求:否
做网站:安全应该在什么时候考虑?
- 漏洞,隐私泄漏~
- 架构一旦确定
- shoiro、SpringSecurity:很像,除了类不一样,名字不一样;
认证,授权(vip1、vip2、vip3)
Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是保护基于Spring的应用程序的事实标准。
Spring Security是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring Security的真正威力在于它可以多么容易地扩展以满足自定义需求
- 功能权限
- 访问权限
- 菜单权限
- 之前拦截器、过滤器,但是需要大量的代码
## 环境搭建
- 创建boot项目
- 引入前段代码和依赖
```
org.springframework.boot
spring-boot-starter-web
org.thymeleaf
thymeleaf-spring5
org.thymeleaf.extras
thymeleaf-extras-java8time
```

- 编写controller
```
package com.wcj.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class RouterController {
@RequestMapping({"/","index"})
public String index(){
return "index";
}
@RequestMapping("toLogin")
public String toLogin(){
return "views/login";
}
@RequestMapping("level1/{id}")
public String level1(@PathVariable("id") int id){
return "views/level1" + id;
}
@RequestMapping("level2/{id}")
public String level2(@PathVariable("id") int id){
return "views/level2" + id;
}
@RequestMapping("level3/{id}")
public String level3(@PathVariable("id") int id){
return "views/level3" + id;
}
}
```
- 启动boot项目,访问localhost:8080

- 如上图进入主页,在没有做安全控制的情况下可以访问任意资源

- 登陆界面

## 简介
Spring Security是针对Spring项目的安全框架,也是spring boot底层安全模块默认的技术选型,他可以实现强大的web安全控制,对于安全控制,我们仅需要引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理
记住几个类:
- WebSecurityConfigurerAdapter:自定义Security策略
- AuthenticationManagerBuilder:自定义认证策略
- @EnablWebSecurity:开启WebSceurity模式
spring Security的两个主要目标是“认证”和“授权”
“认证”(Authentication)
“授权”(Authorization)
这个概念是通用的,而不是只在Spring Security中存在
[参考官网](https://spring.io/projects/spring-security)
[查看我们自己项目中的版本找到对应的帮助文档](https://docs.spring.io/spring-security/site/docs/5.2.0.RELEASE/reference/htmlsingle)
## 使用SpringSecurity
- 导入SpringSecurity依赖
```
org.springframework.boot
spring-boot-starter-security
```

aop思想
- 配置Sceurity
```
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//授权
@Override
protected void configure(HttpSecurity http) throws Exception {
//首页所有人可以访问,功能页只有对应有权限的人才能访问
http.authorizeRequests()//认证一些请求
.antMatchers("/")//认证哪些请求
.permitAll()//哪些人可以访问(这里是所有人all)
.antMatchers("/level1/**")//可以配置多个认证请求
.hasRole("vip1")//哪些人可以访问(这里只有vip1这个角色可以访问)
.antMatchers("/level2/**")//可以配置多个认证请求
.hasRole("vip2")//哪些人可以访问(这里只有vip2这个角色可以访问)
.antMatchers("/level3/**")//可以配置多个认证请求
.hasRole("vip3");//哪些人可以访问(这里只有vip3这个角色可以访问)
}
}
```

继承WebSecurityConfigurerAdapter
重写configure(HttpSecurity http)方法
添加@EnableWebSecurity
- 浏览器访问资源测试

这时首页可以访问,而功能页面需要特定的权限
### 配置自动跳转到登陆页面
```
//没有权限默认回跳转到登陆页面,开启登陆页面
http.formLogin();
```
这时点击功能页面会自动跳转到登陆页面

### 绑定登陆用户
```
//认证,(springboot 2.2.x 可以直接使用)
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//可以从数据库和内存中认证,这里我们使用内存中认证(这些数据正常从数据库中读取)
auth.inMemoryAuthentication()
.withUser("admin").password("123456").roles("vip1","cip2")
.and()
.withUser("root").password("root").roles("vip1","cip2","vip3");
//...
//通过and()可以无限添加用户
}
```
重写configure(AuthenticationManagerBuilder auth)
登陆测试发现报错代码500服务器错误:密码没有编码即没有加密

解决方式:
在springSecurity 5.0+ 中新增了很多加密方式
```
//认证,(springboot 2.2.x 可以直接使用)
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//可以从数据库和内存中认证,这里我们使用内存中认证(这些数据正常从数据库中读取)
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","cip2")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("root")).roles("vip1","cip2","vip3");
//...
//通过and()可以无限添加用户
}
```
### 注销用户
```
//开启注销功能,如果注销成功自动跳转到首页
//http.logout().logoutUrl("/");
http.logout().logoutSuccessUrl("/");
```
浏览器访问资源测试:
注销用户后进入首页访问功能页面则需要重新登陆
### 完善用户登陆权限
首页显示用户信息及登陆状态:
导入整合包:
```
org.thymeleaf.extras
thymeleaf-extras-springsecurity4
3.0.4.RELEASE
```
页面代码:
```
```
测试时发现功能没有生效?
原因:Springboot版本太高,当前使用版本是2.2.1该版本不支持,最高支持2.0.9
注意:降低版本后页面或java代码一些功能实现可能会发生变化。再次测试时关闭csrf或者使用POST方式 (防止网站攻击) 因为登出功能是通过GET方式请求的(即GET请求方式因为明文传输可能会让网站受到攻击)
```
//关闭csrf
http.csrf().disable();
```
#### 动态功能菜单的实现
基于上面的依赖场景
页面代码:
```
```
### 开启记住我功能
```
//开启记住我功能
http.rememberMe();
```
底层cookie实现
### 定制登陆页面
```
//没有权限默认回跳转到登陆页面
http.formLogin().loginPage("/toLogin")
.usernameParameter("user")
.passwordParameter("pwd")
.loginProcessingUrl("login");
//开启记住我功能
http.rememberMe()
.rememberMeParameter("remember");//自定义前端的参数
```
页面代码:
```
记住我
```
## 自动跳转登陆页面原理
```
The most basic configuration defaults to automatically generating a login page at the URL "/login",
redirecting to "/login?error" for authentication failure. The details of the login page can be found on
FormLoginConfigurer.loginPage(String)
```
指定支持基于表单的身份验证。如果未指定FormLoginConfigurer.loginPage(String),则将生成默认登录页面。
配置示例:
最基本的配置默认为在URL“/login”处自动生成登录页面,如果身份验证失败,则重定向到“/login?error”。登录页面的详细信息可以在FormLoginConfigurer.loginPage(String)上找到
```
@Configuration
@EnableWebSecurity
public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
}
The configuration below demonstrates customizing the defaults.
@Configuration
@EnableWebSecurity
public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin()
.usernameParameter("username") // default is username
.passwordParameter("password") // default is password
.loginPage("/authentication/login") // default is /login with an HTTP get
.failureUrl("/authentication/login?failed") // default is /login?error
.loginProcessingUrl("/authentication/login/process"); // default is /login
// with an HTTP
// post
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
}
返回值:
the FormLoginConfigurer for further customizations
抛出:
Exception
请参阅:
FormLoginConfigurer.loginPage(String)
```
## 用户注销原理
提供注销支持。这是在使用WebSecurityConfigurerAdapter时自动应用的。默认情况下,访问URL“/logoout”将使HTTP会话无效,清除已配置的任何rememberMe()身份验证,清除SecurityContextHolder,然后重定向到“/login?success”,从而将用户注销。
自定义配置示例
调用URL“/custom logout”时要注销的以下自定义项。注销将删除名为“remove”的cookie,不会使HttpSession无效,清除SecurityContextHolder,并在完成后重定向到“/logoout success”。
```
@Configuration
@EnableWebSecurity
public class LogoutSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin()
.and()
// sample logout customization
.logout().deleteCookies("remove").invalidateHttpSession(false)
.logoutUrl("/custom-logout").logoutSuccessUrl("/logout-success");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
}
返回值:
the LogoutConfigurer for further customizations
抛出:
Exception
```