Spring Boot + Spring Security + Vue3 + Nginx 跨域与路由配置

发表于 2025-09-09 13:10:32 分类于 默认分类 阅读量 109

好的,我帮你把原来的博客整理优化一下,把内容改成 最终可用方案,重点突出:

  • Spring Boot + Spring Security 统一处理 CORS
  • Nginx 只做代理,不重复加 CORS
  • Vue3 前端路由 fallback 配置
  • 文风简洁,易读

Spring Boot + Spring Security + Vue3 + Nginx 跨域与路由配置实战

在前后端分离项目中,跨域和路由是最常见的两个问题:

  1. 前端 Vue3 SPA 路由访问 /admin 出现 404
  2. Spring Boot 后端跨域请求失败,报 CORS 错误

本文总结了实际项目中的最佳实践,并整理出一套完整可用的解决方案。


1️⃣ Spring Boot 跨域配置

Spring Boot 默认不会返回 CORS 头,需要通过实现 WebMvcConfigurer 来统一配置:

package com.dev.blog.admin.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*") // 允许所有域名
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 支持预检请求
                .allowedHeaders("*") // 允许所有请求头
                .allowCredentials(false) // 不携带 cookie,如果需要改为 true
                .maxAge(3600); // 预检请求缓存时间
    }
}

✅ 建议 只在 Spring Boot 处理 CORS,避免 Nginx 重复添加 Access-Control-Allow-Origin


2️⃣ Spring Security 配置 OPTIONS 放行

启用 Spring Security 后,需要放行所有 OPTIONS 预检请求,否则浏览器跨域会失败:

package com.dev.blog.admin.config;

import com.dev.blog.jwt.JwtAuthenticationSecurityConfig;
import com.dev.blog.jwt.RestAccessDeniedHandler;
import com.dev.blog.jwt.RestAuthenticationEntryPoint;
import com.dev.blog.jwt.TokenAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configurable
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private RestAuthenticationEntryPoint authEntryPoint;
    @Autowired
    private RestAccessDeniedHandler deniedHandler;
    @Autowired
    private JwtAuthenticationSecurityConfig jwtAuthenticationSecurityConfig;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // ⭐ 放行预检
            .mvcMatchers("/admin/**").authenticated() // 后端接口需认证
            .anyRequest().permitAll() // /login 等接口直接放行
            .and()
            .exceptionHandling()
            .authenticationEntryPoint(authEntryPoint)
            .accessDeniedHandler(deniedHandler)
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .apply(jwtAuthenticationSecurityConfig)
            .and()
            .addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    public TokenAuthenticationFilter tokenAuthenticationFilter() {
        return new TokenAuthenticationFilter();
    }

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }
}

/login 可以跨域访问,浏览器预检请求自动通过。


3️⃣ Nginx 配置(只代理,不加 CORS)

Nginx 只负责代理请求,不建议重复加 CORS 头:

server {
    listen 80;
    server_name api.xxx.com;

    location / {
        proxy_pass http://127.0.0.1:8081;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

如果你确实希望 Nginx 返回 CORS 头,也可以在 OPTIONS 请求时直接返回 204,但建议 只在后端处理


4️⃣ Vue3 前端路由 404 问题

Vue3 使用 history 模式,如果 Nginx 没配置 fallback,访问 /admin 等子路由会 404。

Nginx 配置示例:

server {
    listen 80;
    server_name xxx.com;
    root /www/wwwroot/xxx.com;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html; # SPA 路由 fallback
    }
}

5️⃣ 总结

  1. Spring Boot:统一处理 CORS,允许所有域名和方法
  2. Spring Security:放行 OPTIONS 请求,避免预检失败
  3. Nginx:只做代理,避免重复添加 CORS 头
  4. Vue3:在 Nginx 配置 try_files,解决 history 路由 404

配置完成后:

  • /login 可跨域访问
  • /admin/** 接口需要认证
  • Vue3 SPA 子路由 /admin 不会 404
  • 不会再出现 CORS policy 报错
正物博客
一路向前,山海自平