package com.vincent.rsf.server.common.security; import com.vincent.rsf.server.common.constant.Constants; import com.vincent.rsf.server.common.utils.CommonUtil; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.AuthenticationException; 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.stereotype.Component; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.annotation.Resource; import java.io.IOException; /** * Spring Security配置 * */ @Configuration @EnableWebSecurity @EnableMethodSecurity(prePostEnabled = true) public class SecurityConfig { public static final String[] FILTER_PATH = new String[] { "/demo/**", "/test/**", "/system/info", "/tenant/list", "/email/code", "/pda/login", "/erp/**", "/base/**", "/order/**", "/login", "/register", "/druid/**", "/doc.html", "/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/v2/api-docs/**", "/v3/api-docs/**", "/swagger-ui/**", "/ws/**", "/wcs/**", "/monitor/**", "/mcp/**", "/ai/mcp", "/mes/**" }; @Resource private JwtAccessDeniedHandler jwtAccessDeniedHandler; @Resource private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; @Resource private JwtAuthenticationFilter jwtAuthenticationFilter; @Bean public SecurityFilterChain securityFilterChain(org.springframework.security.config.annotation.web.builders.HttpSecurity http) throws Exception { http.authorizeHttpRequests(authorize -> authorize .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() .requestMatchers(HttpMethod.GET, "/file/**", "/captcha", "/").permitAll() .requestMatchers(FILTER_PATH).permitAll() .anyRequest().authenticated()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .csrf(csrf -> csrf.disable()) .cors(cors -> { }) .logout(logout -> logout.disable()) .headers(headers -> headers.frameOptions(frameOptions -> frameOptions.disable())) .exceptionHandling(exceptionHandling -> exceptionHandling .accessDeniedHandler(jwtAccessDeniedHandler) .authenticationEntryPoint(jwtAuthenticationEntryPoint)) .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); } // 没有访问权限异常处理 @Component static class JwtAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException { if (response.isCommitted()) { return; } CommonUtil.responseError(response, Constants.UNAUTHORIZED_CODE, Constants.UNAUTHORIZED_MSG, e.getMessage()); } } // 没有登录异常处理 @Component static class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { if (response.isCommitted()) { return; } CommonUtil.responseError(response, Constants.UNAUTHENTICATED_CODE, Constants.UNAUTHENTICATED_MSG, e.getMessage()); } } }