166 lines
7.7 KiB
Java
166 lines
7.7 KiB
Java
package com.mikufufu.config;
|
||
|
||
import com.mikufufu.modules.auth.security.filter.IllegalRequestFilter;
|
||
import com.mikufufu.modules.auth.security.filter.TokenFilter;
|
||
import com.mikufufu.modules.auth.security.handler.AuthorizationManagerImpl;
|
||
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.authorization.AuthorizationManager;
|
||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||
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.configurers.AbstractHttpConfigurer;
|
||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
|
||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||
import org.springframework.security.web.SecurityFilterChain;
|
||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
|
||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||
import org.springframework.web.cors.CorsConfiguration;
|
||
import org.springframework.web.cors.CorsConfigurationSource;
|
||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||
|
||
import java.util.Arrays;
|
||
import java.util.Collections;
|
||
import java.util.stream.Stream;
|
||
|
||
/**
|
||
* Spring Security配置类
|
||
*
|
||
*/
|
||
@Slf4j
|
||
@Configuration // 表示这是一个配置类
|
||
@EnableWebSecurity // 启用Spring Web安全功能
|
||
@EnableMethodSecurity
|
||
public class SecurityConfig {
|
||
|
||
/**
|
||
* 认证失败处理类:用于处理认证失败的情况。
|
||
*/
|
||
@Autowired
|
||
private AuthenticationEntryPoint authenticationEntryPoint;
|
||
|
||
/**
|
||
* 权限拒绝处理类:用于处理没有权限访问的情况。
|
||
*/
|
||
@Autowired
|
||
private AccessDeniedHandler accessDeniedHandler;
|
||
|
||
// 解决循环依赖的问题
|
||
@Bean
|
||
public AuthorizationManager<RequestAuthorizationContext> authorizationManager(){
|
||
return new AuthorizationManagerImpl();
|
||
}
|
||
|
||
/**
|
||
* 获取匿名访问的权限列表。
|
||
* 匿名权限即不需要用户登录即可访问的资源路径。
|
||
*
|
||
* @return 返回一个包含所有匿名权限路径的列表。
|
||
*/
|
||
private String[] anonymousGet(){
|
||
// 初始化匿名权限路径列表,包括默认权限、Swagger文档权限
|
||
String[] defaultPermission = {"/cache/**","/logout"};
|
||
String[] swaggerPermission = {"/doc.html","/swagger-resources/**","/webjars/**","/v3/api-docs/**","/swagger-ui/**"};
|
||
// 合并权限列表,去除重复项
|
||
return Stream.of(defaultPermission, swaggerPermission)
|
||
.flatMap(Arrays::stream).distinct()
|
||
.toArray(String[]::new);
|
||
}
|
||
|
||
/**
|
||
* 静态资源路径
|
||
* 解决 ** 路径无法匹配的问题
|
||
* @return AntPathRequestMatcher[]
|
||
*/
|
||
private AntPathRequestMatcher[] staticResources(){
|
||
String[] staticPath = {"/","/*.html","/**/*.html","/**/*.js","/**/*.css","/favicon.ico","/image/**"};
|
||
// 创建一个AntPathRequestMatcher数组,用于匹配静态资源路径
|
||
AntPathRequestMatcher[] antPathRequestMatchers = new AntPathRequestMatcher[staticPath.length];
|
||
// 遍历静态资源路径数组,为每个路径创建一个AntPathRequestMatcher对象
|
||
for (int i = 0; i < staticPath.length; i++) {
|
||
antPathRequestMatchers[i] = new AntPathRequestMatcher(staticPath[i]);
|
||
}
|
||
// 返回AntPathRequestMatcher数组
|
||
return antPathRequestMatchers;
|
||
}
|
||
|
||
/**
|
||
* 配置CORS(跨源资源共享)设置,以允许来自特定源的Web请求访问应用程序。
|
||
* 这个方法返回一个CorsConfigurationSource实例,其中包含了对跨域请求的配置。
|
||
* @return UrlBasedCorsConfigurationSource 一个基于URL的CORS配置源,用于指定哪些URL路径应用此CORS配置。
|
||
*/
|
||
@Bean
|
||
public CorsConfigurationSource configurationSource(){
|
||
// 创建一个新的CORS配置对象
|
||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||
// 设置允许的所有请求头
|
||
corsConfiguration.setAllowedHeaders(Collections.singletonList("*"));
|
||
// 设置允许的所有请求方法
|
||
corsConfiguration.setAllowedMethods(Collections.singletonList("*"));
|
||
// 设置允许的请求来源,这里指定了两个来源:本地开发环境和一个示例域名
|
||
// corsConfiguration.setAllowedOrigins(Arrays.asList("http://localhost:8080","https://www.mikufufu.com"));
|
||
corsConfiguration.addAllowedOrigin("*");
|
||
// 设置预检请求(OPTIONS请求)的缓存时间,单位为秒
|
||
corsConfiguration.setMaxAge(3600L);
|
||
// 创建一个新的URL基于的CORS配置源
|
||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||
// 将之前配置的CORS配置应用到所有URL路径
|
||
source.registerCorsConfiguration("/**",corsConfiguration);
|
||
// 返回配置源
|
||
return source;
|
||
}
|
||
|
||
|
||
/**
|
||
* 配置安全过滤链
|
||
* @param http 用于配置HttpSecurity的bean
|
||
* @return 返回配置好的SecurityFilterChain
|
||
* @throws Exception 配置过程中可能抛出的异常
|
||
*/
|
||
@Bean
|
||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||
http
|
||
// 配置CORS跨域资源共享
|
||
.cors(cors -> cors.configurationSource(configurationSource()))
|
||
// 禁用CSRF保护
|
||
.csrf(AbstractHttpConfigurer::disable)
|
||
// 禁用会话创建
|
||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||
// 禁用security默认的注销接口,以解决重定向到login页面时,因为没有登录,所以会重定向到登录页面,但是登录页面没有权限,所以会抛出异常。
|
||
.logout(AbstractHttpConfigurer::disable)
|
||
// 配置请求过滤规则
|
||
.authorizeHttpRequests(authorize -> authorize
|
||
// 放行静态资源
|
||
.requestMatchers(staticResources()).permitAll()
|
||
// 允许GET请求和POST请求
|
||
.requestMatchers(HttpMethod.GET, anonymousGet()).permitAll()
|
||
.requestMatchers(HttpMethod.POST, "/login","/admin/login","/register").permitAll()
|
||
// 使用自定义的权限管理器进行权限检查
|
||
.anyRequest().access(authorizationManager())
|
||
)
|
||
.addFilterBefore(new TokenFilter(), UsernamePasswordAuthenticationFilter.class)
|
||
.addFilterBefore(new IllegalRequestFilter(),TokenFilter.class);
|
||
|
||
// 允许iframe访问
|
||
http.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable));
|
||
|
||
http.exceptionHandling(exceptionHandling ->
|
||
exceptionHandling
|
||
// 认证失败处理
|
||
.authenticationEntryPoint(authenticationEntryPoint)
|
||
// 权限不足处理
|
||
.accessDeniedHandler(accessDeniedHandler));
|
||
|
||
// 构建并返回安全过滤链
|
||
return http.build();
|
||
}
|
||
|
||
}
|
||
|