vue2/3,Spring Boot以及生产环境跨域解决方案

vue2和vue3跨域解决方案

Vue 2 (基于 Webpack) 的跨域解决方案

1. 创建或编辑 vue.config.js 文件

Vue CLI为Webpack项目提供了简单的代理配置方式。你可以通过创建或编辑项目的根目录下的 vue.config.js 文件来设置开发服务器的代理规则:

javascript 复制代码
// vue.config.js
module.exports = {
  devServer: {
    proxy: {
      '/api': { // 代理路径前缀
        target: 'http://backend.example.com', // 后端API的地址
        changeOrigin: true,                   // 更改请求源
        pathRewrite: { '^/api': '' },         // 重写路径,去掉/api前缀
        secure: false,                        // 如果后端是HTTPS,则设置为true,默认false
        logLevel: 'debug'                     // 设置日志级别,方便调试
      }
    }
  }
};

2. 修改前端请求代码

确保你的前端请求都通过 /api 前缀发送,这样它们会被正确代理到后端服务器:

javascript 复制代码
// 在Vue组件或API服务中
import axios from 'axios';

export function fetchDepartments() {
  return axios.get('/api/depts')
    .then(response => response.data)
    .catch(error => console.error('There was an error!', error));
}

Vue 3 (基于 Vite) 的跨域解决方案

Vite使用了一种不同的方式来处理开发服务器的代理配置。它没有像Webpack那样内置的代理配置选项,但可以通过修改 vite.config.js 来实现相同的功能。

使用 Vite 的代理配置

1. 创建或编辑 vite.config.js 文件

你需要在 vite.config.js 中定义一个 server.proxy 属性:

javascript 复制代码
// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue()],
  server: {
    proxy: {
      '/api': {
        target: 'http://backend.example.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
      },
    },
  },
});

2. 修改前端请求代码

同Vue 2一样,确保所有对后端的请求都通过 /api 前缀来发送:

javascript 复制代码
// 在Vue组件或API服务中
import axios from 'axios';

export function fetchDepartments() {
  return axios.get('/api/depts')
    .then(response => response.data)
    .catch(error => console.error('There was an error!', error));
}

Spring Boot 中的 CORS 配置详解

方法 1:使用 @CrossOrigin 注解(局部配置)

@CrossOrigin 注解是最简单的方式,适用于需要为特定控制器或方法启用CORS的情况。你可以通过在控制器类或方法上添加这个注解来实现。

局部配置示例

java 复制代码
// src/main/java/com/example/demo/controller/MyController.java
package com.example.demo.controller;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.ResponseEntity;
import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("/api/depts")
@CrossOrigin(origins = "https://example.com", maxAge = 3600) // 允许的源及缓存时间
public class MyController {

    @GetMapping
    public ResponseEntity<List<String>> getDepts() {
        List<String> depts = Arrays.asList("HR", "Finance", "IT");
        return ResponseEntity.ok(depts);
    }
}

注意事项

  • origins:指定允许的源。
  • maxAge:预检请求的结果可以被缓存的时间(以秒为单位)。
  • allowedHeaders:可选,指定允许的HTTP头。
  • methods:可选,指定允许的HTTP方法。
  • exposedHeaders:可选,指定哪些响应头可以暴露给浏览器。
  • allowCredentials :是否允许凭证(如Cookies)。如果设置为 true,则不能使用通配符 * 作为源。

完整注解参数

java 复制代码
@CrossOrigin(
    origins = {"https://example.com"}, 
    methods = {RequestMethod.GET, RequestMethod.POST},
    allowedHeaders = {"Authorization", "Content-Type"},
    exposedHeaders = {"X-Custom-Header"},
    allowCredentials = "true",
    maxAge = 3600
)

方法 2:全局配置 CORS(WebMvcConfigurer)

如果你想要为所有端点配置CORS,或者定义多个CORS配置,可以通过实现 WebMvcConfigurer 接口并重写 addCorsMappings 方法来进行全局配置。

全局配置示例

java 复制代码
// src/main/java/com/example/demo/config/WebConfig.java
package com.example.demo.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 WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 匹配所有路径
                .allowedOrigins("https://example.com") // 允许的源
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许的HTTP方法
                .allowedHeaders("*") // 允许的HTTP头
                .allowCredentials(true) // 是否允许凭证
                .maxAge(3600); // 预检请求结果缓存时间(秒)
    }
}

注意事项

  • allowedOrigins :指定允许的源,可以是一个具体的URL,也可以是通配符 * 表示允许所有源。但是,如果你启用了凭证共享 (allowCredentials=true),则不能使用通配符 *
  • allowedMethods:指定允许的HTTP方法。
  • allowedHeaders:指定允许的HTTP头。
  • allowCredentials :如果设置为 true,则意味着响应将包含 Access-Control-Allow-Credentials 头,这会告诉浏览器是否允许发送凭证信息(例如cookies)。如果启用了凭证,则不能将 allowedOrigins 设置为 *
  • maxAge:预检请求的结果可以被缓存的时间(以秒为单位)。

多路径配置示例

如果你需要为不同路径设置不同的CORS规则,可以在 addCorsMappings 方法中注册多个映射:

java 复制代码
@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/api/**")
            .allowedOrigins("https://example.com")
            .allowedMethods("GET", "POST")
            .allowedHeaders("Authorization", "Content-Type")
            .allowCredentials(true)
            .maxAge(3600);

    registry.addMapping("/admin/**")
            .allowedOrigins("https://admin.example.com")
            .allowedMethods("GET", "POST", "PUT", "DELETE")
            .allowedHeaders("*")
            .allowCredentials(false)
            .maxAge(3600);
}

方法 3:通过 CorsFilter 配置

对于更复杂的场景,比如你需要对不同的路径应用不同的CORS规则,或者你希望在应用程序启动时就注册CORS过滤器,你可以创建一个 CorsConfigurationSource 并注册一个 CorsFilter

自定义 CorsFilter 示例

java 复制代码
// src/main/java/com/example/demo/config/CorsConfig.java
package com.example.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        // Path 1: /api/*
        CorsConfiguration apiConfig = new CorsConfiguration();
        apiConfig.setAllowCredentials(true);
        apiConfig.addAllowedOrigin("https://example.com");
        apiConfig.addAllowedHeader("Authorization");
        apiConfig.addAllowedHeader("Content-Type");
        apiConfig.addAllowedMethod("GET");
        apiConfig.addAllowedMethod("POST");
        source.registerCorsConfiguration("/api/**", apiConfig);

        // Path 2: /admin/*
        CorsConfiguration adminConfig = new CorsConfiguration();
        adminConfig.setAllowCredentials(false);
        adminConfig.addAllowedOrigin("https://admin.example.com");
        adminConfig.addAllowedHeader("*");
        adminConfig.addAllowedMethod("*");
        source.registerCorsConfiguration("/admin/**", adminConfig);

        return new CorsFilter(source);
    }
}

多路径配置示例

如果你有多个路径需要不同的CORS规则,可以在 UrlBasedCorsConfigurationSource 中注册多个配置:

java 复制代码
@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

    // Path 1: /api/*
    CorsConfiguration apiConfig = new CorsConfiguration();
    apiConfig.setAllowCredentials(true);
    apiConfig.addAllowedOrigin("https://example.com");
    apiConfig.addAllowedHeader("Authorization");
    apiConfig.addAllowedHeader("Content-Type");
    apiConfig.addAllowedMethod("GET");
    apiConfig.addAllowedMethod("POST");
    source.registerCorsConfiguration("/api/**", apiConfig);

    // Path 2: /admin/*
    CorsConfiguration adminConfig = new CorsConfiguration();
    adminConfig.setAllowCredentials(false);
    adminConfig.addAllowedOrigin("https://admin.example.com");
    adminConfig.addAllowedHeader("*");
    adminConfig.addAllowedMethod("*");
    source.registerCorsConfiguration("/admin/**", adminConfig);

    return new CorsFilter(source);
}

高级配置选项

1. 处理凭证共享

当你需要处理凭证(如Cookies)时,确保正确设置了 allowCredentialsallowedOrigins。记住,如果启用了凭证共享,你不能使用通配符 * 作为允许的源。

java 复制代码
config.setAllowCredentials(true);
config.addAllowedOrigin("https://example.com"); // 必须明确指定源
2. 处理复杂头部

有时你需要处理特定的HTTP头部,而不是简单的通配符。你可以通过 setAllowedHeaders 方法来指定允许的头部。

java 复制代码
config.addAllowedHeader("Authorization");
config.addAllowedHeader("Content-Type");
3. 处理多种来源

如果你有多个允许的来源,可以使用 setAllowedOrigins 方法来添加多个源。

java 复制代码
config.addAllowedOrigin("https://example.com");
config.addAllowedOrigin("https://anotherdomain.com");
4. 处理预检请求

预检请求(Preflight Requests)是在某些跨域请求之前由浏览器自动发送的,用于检查服务器是否允许实际请求。你可以通过 setAllowCredentialssetMaxAge 来控制这些行为。

java 复制代码
config.setAllowCredentials(true);
config.setMaxAge(3600L); // 缓存预检请求结果的时间(秒)
5. 暴露特定响应头

有时候你需要让客户端能够访问某些特定的响应头。你可以通过 setExposedHeaders 方法来指定这些响应头。

java 复制代码
config.setExposedHeaders(Arrays.asList("X-Custom-Header"));

生产环境下的解决方案

1. 使用 Nginx 反向代理

Nginx 是一个高性能的HTTP和反向代理服务器,它可以帮助你将前端请求转发到后端API服务器,同时处理跨域问题。通过这种方式,你可以确保所有的请求都来自同一个域名,从而避免浏览器的同源策略限制。

Nginx 配置示例

假设你的前端应用部署在 http://example.com,而后端API位于 http://backend.example.com。你可以使用Nginx来设置反向代理:

javascript 复制代码
# /etc/nginx/sites-available/example.com
server {
    listen 80;
    server_name example.com;

    location / {
        # 将所有前端静态资源请求指向Vue构建的静态文件目录
        root /var/www/html/dist;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        # 将/api/开头的请求转发给后端API服务器
        proxy_pass http://backend.example.com/;
        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;
    }
}

步骤:

  1. 安装 Nginx(如果尚未安装):

    bash 复制代码
    sudo apt update
    sudo apt install nginx
  2. 配置 Nginx

    • 创建或编辑 /etc/nginx/sites-available/example.com 文件。
    • 使用上述配置示例进行修改,确保路径和域名正确。
  3. 启用站点配置

    bash 复制代码
    sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
  4. 测试配置并重启 Nginx

    bash 复制代码
    sudo nginx -t
    sudo systemctl restart nginx
  5. 部署前端静态文件

    • 将Vue构建后的静态文件放置在 /var/www/html/dist 目录下。
  6. 确保后端API服务器正常运行

    • 确认 http://backend.example.com 可以访问,并且API服务正常工作。

2. 前后端部署在同一域名下

如果可能的话,将前后端部署在同一域名下是解决跨域问题的最佳实践之一。这样做可以完全避免跨域问题,因为所有请求都来自同一源。

示例:

  • 前端 :部署在 https://example.com
  • 后端API :部署在 https://api.example.com

如果你使用的是子域名(如 api.example.com),你可以通过DNS配置和SSL证书来确保它们被视为同一源。另外,也可以考虑将API路由集成到主域名中(例如 https://example.com/api)。

相关推荐
天空之外1364 小时前
Spring Boot Actuator、Spring Boot Actuator使用、Spring Boot Actuator 监控、Spring程序监控
java·spring boot·spring
B1nnnn丶4 小时前
通用导出任何对象列表数据的excel工具类
java·spring boot·excel
赛博末影猫4 小时前
SpringBoot(Ⅱ-2)——,SpringBoot版本控制,自动装配原理补充(源码),自动导包原理补充(源码),run方法
java·spring boot·后端
光岳楼观景4 小时前
Springboot -- JSON
spring boot·后端·json
百年bd4 小时前
AI对话机器人简单实现--智谱BigModel+SpringBoot+Vue2+ElementUI
spring boot·elementui·vue2·ai助手·智谱ai·ai对话机器人
光岳楼观景6 小时前
SpringBoot -- Docker Compose的支持
spring boot·docker·eureka
欣栀♡6 小时前
Nginx性能优化全方案:打造一个高效服务器
服务器·前端·nginx
骑着王八撵玉兔8 小时前
【Spring Boot 】详解
java·数据库·spring boot·后端·spring·spring cloud
陶然同学8 小时前
【畅购商城】微信支付之支付模块
java·spring boot·后端·mysql·微信
AI人H哥会Java8 小时前
【Spring】基于XML的Spring容器配置——FactoryBean的使用
java·开发语言·spring boot·后端·spring·架构