Spring security 框架
什么是Spring security框架?
- Spring security 是Spring 家族提供的一款安全管理框架
- Spring security 是一个功能强大且高度可定制的一款身份验证和访问控制框架,它用于保护Spring应用的实际标准
- Spring Security是一个框架,致力于为Java应用程序提供身份验证和授权。与所有Spring项目一样,Spring Security的真正强大之处在于可以轻松扩展以满足自定义要求。
- 在 Java 生态中,目前有 Spring Security 和 Apache Shiro 两个安全框架,可以完成认证和授权的功能。
Spring security使用之前需要注意什么?
在使用Spring security框架之前,我们要确保自己所写项目的所有功能可以正常使用,因为一旦开始使用该框架,我们项目中所有请求都需要经过该框架的验证才可以正常使用,经过重重验证才可以测试之前请求,所以一般建议在我们所有功能已经完善的情况下再使用Spring security框架
Spring security使用流程是什么?
- 导入spring-boot-starter-security启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
当添加了以上依赖之后,当前项目会:
-
此依赖项中包含BCryptPasswordEncoder类,可以用于处理密码加密
-
所有请求都是必须通过认证的,在没有通过认证之前,任何请求都会被重定向到Spring security内置的登录页面(Spring security自动为我们提供一个登录表单)
- 可以使用user作为用户名,使用启动项目时随机生成的UUID密码来登录(当我们项目启动后,控制台会自动为我们生成一条UUID密码,通过用户名:root,密码:UUID密码就可以成功登录)
- 当登录成功后,会自动重定向到此前访问的页面(当我们访问哪个请求路径弹出内置表单,登陆成功后就会重定向到该请求路径对应的哪个页面)
- 当登录成功后,所有的GET的异步请求允许访问,单POST的异步请求不允许访问(会报403错误)
403:错误是由于"执行"访问被禁止而造成的,也就是我们没有权限访问该请求,这里我们就是登录成功,Spring security默认允许GET异步请求,POST异步请求被禁止访问
添加完依赖后,在浏览器中尝试访问时还可能出现以下错误:
org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the header value "Idea-c968a669=03021799-4633-4321-9d0d-11b7ee08f588; username=黄汉å‡; JSESSIONID=120F9329E0CE7AF9E052A302EFE494F2" is not allowed.
此错误是浏览器导致的,更换浏览器即可.
-
创建Spring security 的配置类
创建一个Spring security的配置类,自定义命名,这里我命名为SecurityConfiguration,该类需要继成WebSecurityConfigurerAdapter类,并重写其中的 configure() 方法
package cn.tedu.csmall.passport.config;
import cn.tedu.csmall.passport.filter.JwtAuthorizationFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.UsernamePasswordAuthenticationFilter;
/**
* SpringSecurity配置类
*
* @author maKai
* @date 2022/11/7 10:35
*/
@Configuration
@Slf4j
@EnableGlobalMethodSecurity(prePostEnabled = true)//启用方法级别的权限检查
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthorizationFilter jwtAuthorizationFilter;
public SecurityConfiguration() {
log.debug("创建配置类对象对象:SecurityConfiguration");
}
/**
* security提供用于底层自动验证用户名和密码的接口
* 该接口用于在登录业务层使用,对用户名密码进行验证
* @return
* @throws Exception
* AuthenticationManager接口实现类下有以下俩个方法用于用户名密码验证
* authenticationManager():该方法如果项目中没有登录验证,会试测试类中一些测试死循环执行,造成内存溢出,大大降低系统性能
* authenticationManagerBean():该方法与authenticationManager()作用一样,就是不会出现内存溢出现象
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* 配置密码编码器
*
* @return NoOpPasswordEncoder.getInstance()不会对密码进行加密处理,不推荐
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 如果不调用父类方法,默认所有请求都不需要通过验证,可以直接访问
// super.configure(http);
//白名单
/*
/**:表示可以匹配多级目录,/a,/b,/a/b
/*:只能匹配以及目录
*/
String[] urls = {
"/doc.html",
"/**/*.js",
"/**/*.css",
"/swagger-resources",
"/v2/api-docs",
"/admins/login"
};
//提示:关于请求路径的配置,如果有多个mvcMatchers配置,以第一次配置为准
http.authorizeRequests()//管理请求授权
// .mvcMatchers(HttpMethod.OPTIONS,"/**")
// .permitAll()//对于请求跨域访问请求OPTIONS直接许可放行(它与http.cors作用一样)
.mvcMatchers(urls)//匹配某些路径/**所有请求都要经过认证
.permitAll()//直接许可,不需要通过认证
.anyRequest()//除了上边配置以外的其它请求
.authenticated();//要求是已经通过认证的(需要认证),post:403,get:200
//解决spring security 复杂请求触发的预检(触发预检浏览器会自动向服务器发送一个OPTIONS类型的请求,此请求被正常访问才可以提交原本请求)导致跨域访问问题(启用cors过滤器)
http.cors();
//将防止伪造跨域攻击的机制禁用(加上此代码,只要通过验证,post,get请求都可以访问),此种方式是不安全的,当我们在x选项卡登录成功后,Y选项卡也默认登陆成功
http.csrf().disable();
//将我们的JWT过滤器添加到Spring security过滤器链当中(且需要添加到靠前位置)
http.addFilterBe