跨域问题(vue2 + springboot)

一、前端的配置

在vue项目中进行配置, 从而使 /api 开头的请求都会被代理到制定的域名, 从而避免跨域问题

1.1 在 vue.config.js 文件中添加如下配置

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://your-api-server.com', // 目标接口的域名
        changeOrigin: true, // 是否跨域
        pathRewrite: {
          '^/api': '' // 重写路径,去掉 `/api` 前缀
        }
      }
    }
  }
}

1.2 在 axios 的请求中, 需要使用 /api 作为前缀

axios.get('/api/some-endpoint')
  .then(response => {
    console.log(response.data);
  })
  .catch(error => {
    console.error(error);
  });

二. 在后端配置

2.1 添加全局配置

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("/**")
                .allowedOrigins("http://localhost:80") // 明确指定允许的域名
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowedHeaders("*")
                .allowCredentials(true) // 允许凭证
                .maxAge(3600);
    }
}

注:

    1. 如果不需要凭证(如 Cookies 或 Authorization 头),可以将 allowCredentials 设置为 false
    1. 当使用 .allowedOrigins("*") 报错 When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.] with root cause , 则需要明确制定允许的域名
    1. 当已经重写过 WebMvcConfigurer 的其余实现类时, 再次添加 CorsConfig 可能会被覆盖而导致失效
    1. 快捷键 ctrl + H 查看结构层次, 确定 WebMvcConfigurer 是否已经被重写

2.2 使用 CorsFilter

当需要更细粒度的控制时, 可以使用 CorsFilter

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();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true); // 允许凭证
        config.addAllowedOrigin("http://localhost:80"); // 明确指定允许的域名
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

2.3 在 Controller 上单独配置

当只需要为某些 Controller 或方法配置 CORS,可以使用 @CrossOrigin 注解

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin(origins = "http://localhost:80", allowCredentials = "true") // 明确指定允许的域名
public class MyController {

    @GetMapping("/api/data")
    public String getData() {
        return "Hello from Java backend!";
    }
}

三. 什么是跨域问题

跨域问题是在网络开发中,当一个网页或应用程序试图从一个域名(源)去访问另一个不同域名(目标)的数据或资源时,由于浏览器的同源策略限制而引发的问题。

产生原因

  • 同源策略:这是浏览器的一种安全机制,它要求浏览器在执行脚本、请求数据等操作时,确保请求的源(协议、域名、端口号)与当前页面的源相同。例如,https://www.example.com与https://www.example.net,虽然主域名相似,但仍是不同域名,若从前者页面去访问后者资源就会触发跨域问题。
  • 实际应用需求:在现代 Web 开发中,经常会出现需要从不同域名获取数据或资源的情况。比如,一个网站可能需要调用第三方的 API 来获取数据,或者加载来自 CDN(内容分发网络)的静态资源等,这些操作很容易导致跨域请求的发生。

常见场景

  • AJAX 请求跨域:在使用 JavaScript 的 AJAX 技术向不同域名的服务器请求数据时,如果服务器没有进行相应的配置允许跨域访问,就会出现跨域问题。浏览器会阻止这种跨域的 AJAX 请求,并在控制台中显示错误信息。
  • 跨域加载脚本、样式和图片:虽然浏览器通常允许跨域加载一些静态资源,如脚本、样式表和图片,但在某些情况下,如果服务器配置不当或者需要进行更精细的权限控制,也可能会出现跨域问题。比如,当尝试通过<script>标签加载一个来自不同域名的 JavaScript 文件时,如果目标服务器不允许跨域访问,可能会导致脚本无法加载或执行。
  • iframe 跨域:当在一个页面中使用<iframe>标签嵌入另一个不同域名的页面时,两个页面之间的交互可能会受到跨域限制。例如,父页面想要访问 iframe 子页面中的内容或执行子页面中的脚本,就可能会因为跨域问题而失败。

解决方法

  • CORS(跨域资源共享):这是一种在服务器端进行配置的机制,通过在服务器响应头中添加特定的字段,来告诉浏览器哪些域名可以访问该服务器的资源,以及允许进行哪些类型的跨域操作。例如,服务器可以设置Access-Control-Allow-Origin头来指定允许访问的源。
  • JSONP(JSON with Padding):利用<script>标签没有跨域限制的特点,通过动态创建<script>标签来请求数据,并在服务器端将数据以特定的格式返回,在客户端通过回调函数来处理返回的数据。不过,JSONP 只支持 GET 请求,有一定的局限性。
  • 代理服务器:在客户端和目标服务器之间搭建一个代理服务器,客户端先将请求发送到代理服务器,代理服务器再将请求转发到目标服务器,并将目标服务器的响应返回给客户端。这样,对于客户端来说,所有的请求都是在同一个域名下进行的,从而避免了跨域问题。

四. 为什么有浏览器的同源策略限制

浏览器的同源策略限制是一种重要的安全机制,主要是为了防止恶意网站窃取用户信息、执行恶意操作等

保护用户隐私和数据安全

  • 防止跨站脚本攻击(XSS):恶意网站可能会利用同源策略的缺失,在用户访问的合法页面中注入恶意脚本。如果没有同源策略,这些脚本就能够获取用户在该页面上输入的敏感信息,如用户名、密码、信用卡号等,然后将这些信息发送给攻击者。例如,用户在银行网站登录后,如果另一个恶意网站可以随意访问银行网站的内容,就可能通过脚本获取用户的银行账户信息,导致用户资金被盗。
  • 保护用户浏览历史等信息:同源策略可以防止一个网站随意读取用户在其他网站的浏览历史、Cookie 等信息。这些信息可能包含用户的个人偏好、登录状态等敏感内容,如果被恶意网站获取,可能会被用于精准的广告投放、用户画像分析,甚至是进一步的攻击。

防止数据篡改和恶意操作

  • 防止跨站请求伪造(CSRF):攻击者可能会构造一个恶意链接或页面,诱导用户点击。如果没有同源策略限制,当用户登录了某个网站(如购物网站、社交网站等)并处于登录状态时,点击了恶意链接,恶意网站可能会利用用户的登录状态,向目标网站发送请求,执行一些用户不知情的操作,如修改用户密码、发送恶意邮件、进行购物下单等。同源策略能够限制跨域请求,使得目标网站可以验证请求是否来自合法的源,从而防止此类攻击。
  • 保护网站数据完整性:对于一些需要进行数据交互和操作的网站,如在线文档编辑、企业管理系统等,同源策略可以确保只有来自同一源的请求才能对数据进行修改和操作。否则,恶意网站可能会随意篡改这些数据,导致数据丢失、错误或混乱,影响网站的正常运行和用户的正常使用。

维护浏览器环境的稳定性和安全性

  • 防止恶意脚本干扰:不同网站的脚本可能会有不同的功能和行为,如果没有同源策略,这些脚本可能会在用户不知情的情况下相互干扰、冲突,甚至破坏浏览器的正常运行。例如,一个网站的脚本可能会修改浏览器的全局变量或对象,影响其他网站脚本的正常执行,导致页面出现错误或异常。
  • 限制代码执行权限:同源策略可以根据不同的源为脚本分配不同的权限和执行环境,使得脚本只能在其所属的源范围内进行操作,避免恶意脚本在浏览器中获得过高的权限,从而防止脚本对浏览器本身以及用户的设备进行恶意操作,如删除文件、获取系统信息等。
### 部署 Vue3 和 Spring Boot 组合项目的最佳实践 #### 准备工作 为了成功部署基于 Vue3 和 Spring Boot 的 Web 应用程序,需确保环境已准备好必要的工具和服务。这包括安装 Node.js 用于构建前端资源,Java 开发套件 (JDK) 支持 Spring Boot 后端运行。 #### 构建与打包前端项目 在完成前端开发后,应当通过 npm 或 yarn 执行生产模式下的编译命令来准备静态文件。这些文件会被放置在一个特定目录下,默认情况下通常是 `dist` 文件夹内[^1]。 ```bash npm run build ``` 此过程会优化并压缩 JavaScript、CSS 及其他资产文件以便于高效分发给最终用户访问。 #### 修改 Spring Boot 以支持前端静态资源服务 为了让 Spring Boot 能够正确提供由 Vue CLI 创建出来的 HTML 页面及其他静态资源,在主应用程序类中加入如下配置: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 还需调整 application.properties 或者 yml 来指定静态内容路径指向之前提到过的 dist 目录中的 index.html 文件位置,并开启 CORS 支持请求[^2]。 ```properties server.servlet.context-path=/ spring.resources.static-locations=file:./build/,classpath:/static/ management.endpoints.web.exposure.include=* ``` 对于更复杂的场景比如代理 API 请求,则可以考虑使用 Nginx 或 Apache HTTP Server 进行反向代理设置;而对于简单的应用场景可以直接让 Spring Boot 处理所有的HTTP流量。 #### 容器化解决方案 采用 Docker 技术将整个应用及其依赖项封装成容器镜像是一种现代化的做法。创建两个独立的服务——一个是针对 Java 应用的官方 OpenJDK 映像加上自定义 JAR 包启动脚本;另一个则是带有 NGINX 的映像负责托管经过预渲染后的单页应用程序(SPA)[^4]。 Dockerfile 示例: ```dockerfile FROM openjdk:17-jdk-alpine AS builder WORKDIR /app COPY target/*.jar app.jar ENTRYPOINT ["java", "-jar","/app/app.jar"] FROM nginx:alpine COPY --from=builder /app/build /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] ``` #### 发布到云平台 最后一步就是选择合适的云计算提供商如 AWS Elastic Beanstalk、Google Cloud Platform App Engine Standard Environment 或 Microsoft Azure Web Apps 等来进行线上发布操作了。大多数主流服务商均提供了良好的文档指导开发者顺利完成迁移流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值