fix(security): resolve SPA frontend route refresh returning 401

This commit is contained in:
matevip 2026-04-05 18:20:40 +08:00
parent c8f3a12925
commit 732bb13f47
2 changed files with 36 additions and 24 deletions

View File

@ -48,34 +48,20 @@ public class SecurityConfig {
)
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
// 公开接口
// 公开 API 接口
.requestMatchers(
"/api/v1/auth/login",
"/api/v1/settings/language",
"/swagger-ui.html",
"/swagger-ui/**",
"/v3/api-docs/**",
"/webjars/**",
"/actuator/**",
"/h2-console/**",
// 静态资源前端 SPA
"/",
"/index.html",
"/assets/**",
"/icons/**",
"/logo/**",
"/favicon.ico"
"/api/v1/agents/*/chat/stream",
"/api/v1/chat/stream",
"/api/v1/chat/*/stop",
"/api/v1/setup/**",
"/api/v1/channels/webhook/**"
).permitAll()
// SSE 流式接口允许匿名开发模式生产环境可改为 authenticated
.requestMatchers("/api/v1/agents/*/chat/stream").permitAll()
.requestMatchers("/api/v1/chat/stream").permitAll()
.requestMatchers("/api/v1/chat/*/stop").permitAll()
// 初始化 Setup API首次安装语言选择无需认证
.requestMatchers("/api/v1/setup/**").permitAll()
// 渠道 Webhook 回调各平台消息推送由平台签名机制保障安全
.requestMatchers("/api/v1/channels/webhook/**").permitAll()
// 其余接口需要认证
.anyRequest().authenticated()
// 所有其他 API 接口需要认证
.requestMatchers("/api/**").authenticated()
// API 请求前端路由静态资源SwaggerH2 Console 全部放行
.anyRequest().permitAll()
)
.exceptionHandling(ex -> ex
.authenticationEntryPoint((request, response, authException) -> {

View File

@ -0,0 +1,26 @@
package vip.mate.config;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
/**
* SPA 前端路由 Fallback
* <p>
* 将不含扩展名的 GET 请求转发到 index.html Vue Router 接管客户端路由
* 路径段正则 {@code [^\\.]*} 排除含 "." 的路径静态资源如 .js/.css/.ico
* 同时 Spring MVC 会优先匹配 @RestController 精确路由因此不会影响 /api/** 接口
*
* @author MateClaw Team
*/
@Controller
public class SpaForwardController {
@GetMapping(value = {
"/{path:[^\\.]*}",
"/{path1:[^\\.]*}/{path2:[^\\.]*}",
"/{path1:[^\\.]*}/{path2:[^\\.]*}/{path3:[^\\.]*}"
})
public String forward() {
return "forward:/index.html";
}
}