package com.example.demo.security; import com.example.demo.domain.vo.Result; import jakarta.servlet.http.HttpServletResponse; 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.authentication.configuration.AuthenticationConfiguration; 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.EnableWebSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; /** * SpringSecurity的配置文件 */ @Configuration @EnableWebSecurity // 开启Security的支持 @EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法注解 public class SecurityConfig { @Autowired TokenFilter tokenFilter; // 核心配置 配置一个过滤器链 @Bean public SecurityFilterChain configure(HttpSecurity http) throws Exception { // 这里可以对httpSecurity进行详细的配置 链式调用的配置方式 http.formLogin(AbstractHttpConfigurer::disable) // 方法引用,禁用表单登录 .logout(AbstractHttpConfigurer::disable) // 禁用默认退出 .csrf(AbstractHttpConfigurer::disable) // 禁用csrf的保护,分布式的前后端分离的项目 // 设定CORS .cors(cors -> cors.configurationSource(corsConfigurationSource())) // 禁用Session, .sessionManagement( session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 用户未登录的处理 .exceptionHandling( exception -> exception.authenticationEntryPoint(authenticationEntryPoint())) // 用户权限不足的处理 .exceptionHandling( exception -> exception.accessDeniedHandler(accessDeniedHandler())) // 配置路径拦截 .authorizeHttpRequests( request -> request .requestMatchers( HttpMethod.POST, // 用户不登录就可以访问的路径 "/admin/login","/upload/**","/detailY/ERP").permitAll() .requestMatchers( "/error","alipay/**","/upload/**" ).permitAll() .anyRequest().authenticated() // 其它路径,必须要登录后才能访问 ); http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class); // 然后是TokenFilter return http.build(); } /** * 1. 配置认证管理器 * @param config * @return * @throws Exception */ @Bean protected AuthenticationManager authenticationManager( AuthenticationConfiguration config ) throws Exception { return config.getAuthenticationManager(); } /** * 2. 密码编码器 * @return */ @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } /** * 3. 用户未登录时的错误处理 * @return */ @Bean public AuthenticationEntryPoint authenticationEntryPoint() { return ( request, response, authException) -> { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 response.setContentType("application/json; charset=utf-8"); response.getWriter().write(Result.error("用户未登录").toJson()); }; } /** * 4. 权限不足时的处理 * @return */ @Bean public AccessDeniedHandler accessDeniedHandler() { return ( request, response, authException) -> { response.setStatus(HttpServletResponse.SC_FORBIDDEN); // 403 response.setContentType("application/json; charset=utf-8"); response.getWriter().write(Result.error("当前用户权限不足!").toJson()); }; } /** * 5. 配置跨域请求 * @return */ @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOriginPattern("*"); // 允许任何的源 config.addAllowedMethod("*"); // 允许任何的HTTP请求方式 config.addAllowedHeader("*"); // 允许任何的HTTP头 config.setAllowCredentials(true); // 允许证书 config.setMaxAge(3600L); // 设置浏览器预检的时间 // 生成源 UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } }