SpringBoot + Vue前后端分离开发的跨域问题

本文涉及的产品
.cn 域名,1个 12个月
简介: 解决SpringBoot + Vue前后端分离开发的跨域问题

SpringBoot + Vue前后端分离开发的跨域问题

文章目录

  • SpringBoot + Vue前后端分离开发的跨域问题
  • 一个因跨域问题报错的例子
  • 跨域问题与浏览器的同源策略
  • 如何解决跨域问题
  • 后端来解决
  • 前端来解决

一个因跨域问题报错的例子

  我们以一个简单的springboot + vue前后端分离小例子来引入跨域问题,我们要从前端输入一个字符串,然后通过ajax发送请求将这个字符串传给后端,由后端接收并打印出来

  这个例子十分简单,我们直接上代码:

  后端:

@RestController
@RequestMapping("/data")
public class GetAndPrintData {
    @PostMapping("/put/string")
    public void getAndPrintString(@RequestBody StringData stringData) {
        System.out.println(stringData.getStringData());
    }
}
@Data
public class StringData {
    private String stringData;
}

  前端:

<template>
  <div>
    <el-form ref="dataForm" :model="dataForm" label-width="80px" class="login-box">
      <h3 class="login-title">来传输数据</h3>
      <el-form-item label="字符串数据" prop="stringData">
        <el-input type="text" placeholder="请输入字符串信息" v-model="dataForm.stringData"/>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" v-on:click="onSubmit()">传输数据</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
export default {
  name: "CrosTest",
  data() {
    return {
      dataForm: {
        stringData: ''
      },
    }
  },
  methods: {
    onSubmit() {
      axios({
        method: 'POST',
        url: 'http://localhost:8181/data/put/string',
        data: this.dataForm
      })
    }
  }
}
</script>
<style scoped>
</style>

  这里要注意的点是前端传的JSON中的key要和后端实体类中的属性对应,后端实体类属性为stringData,前端传的JSON中的key也要为stringData,若为stringdata,则对应不上,后端将接收不到相应数据

  我们启动前后端后,输入字符串并提交,发现前端报错,后端没有接收到数据

e71e69b06e6d46daaeab5f9074ee6ead.png

  来看看具体的报错信息:

Access to XMLHttpRequest at 'http://localhost:8181/data/put/string' from origin 'http://localhost:8081' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

  它说我们的http请求被CORS policy给blocked了,那么什么是CORS policy呢?接下来我们就来谈谈跨域问题

跨域问题与浏览器的同源策略

  什么是跨域呢?浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域。在我们的前后端分离开发中,首先,前后端端口就一定不同,也就是说,前端发请求到后端一定是跨域。与跨域相对的概念就是同源,两个页面地址中的协议,域名,端口号一致,则表示同源。

  浏览器采用了同源策略。同源策略保证了以下3点:

  1、无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB

  2、无法接触非同源网页的 DOM(HTML DOM 定义了用于 HTML 的一系列标准的对象,以及访问和处理 HTML 文档的标准方法)

  3、无法成功向非同源地址发送 AJAX 请求(可以发送,但浏览器会拒绝接受响应)

  为什么浏览器要采取同源策略呢?主要是为了保证安全,如果没有同源限制存在,浏览器中的cookie等其他数据可以任意读取,不同域下DOM任意操作,ajax任意请求的话,如果浏览了恶意网站那么就会泄漏这些隐私数据,恶意程序也能给别的网站疯狂进行ajax请求。

  我们之前的例子就是因为向非同源地址发送了ajax请求,被浏览器的同源策略拒绝了

如何解决跨域问题

后端来解决

  既然无法成功向非同源地址发送 AJAX 请求,那有没有出现什么方法来解决这个问题呢,毕竟我们是要经常发送跨域请求的。W3C制定了一个标准CORS,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

  CORS需要浏览器和服务器同时支持,浏览器这端完全不用担心,目前的浏览器一般没有不支持的。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。这就是后端的任务了。

  这种方法是跨源 AJAX 请求的根本解决方法。

  因此,我们只要让后端实现CORS接口就好了,CORS接口的具体细节可以参考:跨域资源共享 CORS 详解

  我们使用@Configuration注解创建一个配置类,该配置类需实现WebMvcConfigurer接口,这里提供两种方式来进行配置:

  方法1:配置类里面使用@Bean标注在构造器方法上用以注入一个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;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class Configurer implements WebMvcConfigurer {
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);   // 可选字段,表示是否允许发送Cookie,true表示允许
        config.addAllowedOrigin("http://localhost:8081");   // 必填字段,"*"表示接受任意域名的请求
        config.addAllowedHeader("*");   // 可选字段,允许CORS请求额外发送的头信息字段
        config.addAllowedMethod("*");   // 必填字段,允许CORS请求使用的HTTP方法, "*"表示全部方法
        config.setMaxAge(3600L);    // 可选字段,用来指定预检请求的有效期,单位为秒。在有效期间,不用发出另一条预检请求
        source.registerCorsConfiguration("/**", config);    // 必填字段,"/**"表示请求路径是多级,"/*/*"表示请求路径是两级
        return new CorsFilter(source);
    }
}

  方法2:配置类重写addCorsMappings方法,若该配置类只负责CORS配置,则可使用此方法:

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 Configurer implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")  // 必填字段,"/**"表示请求路径是多级,"/*/*"表示请求路径是两级
                .allowedOriginPatterns("http://localhost:8081")     // 必填字段,"*"表示接受任意域名的请求
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")  // 必填字段,允许CORS请求使用的HTTP方法, "*"表示全部方法
                .allowCredentials(true)     // 可选字段,表示是否允许发送Cookie,true表示允许
                .maxAge(3600)   // 可选字段,用来指定预检请求的有效期,单位为秒。在有效期间,不用发出另一条预检请求
                .allowedHeaders("*");   // 可选字段,允许CORS请求额外发送的头信息字段
    }
}

  这里对上述代码解释一下,Origin字段在CORS中用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。我们在配置中设置了allowCredentials(true),表示允许发送Cookie,此时allowedOriginPatterns就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也无法读取服务器域名下的Cookie,这也是为了安全考虑,因此我们将允许的OriginPatterns设为前端域名http://localhost:8081。同时由于Cookie的收发前后端都要参与,必须在AJAX请求中打开withCredentials属性,我们要在vue项目的main.js中加上这样一句配置:axios.defaults.withCredentials=true;

11.png

  不加上这句配置,即使服务器同意发送Cookie,浏览器也不会发送。或者,服务器要求设置Cookie,浏览器也不会处理。

  下面我们来测试一下:

22.png

33.png

  成功解决了跨域问题

前端来解决

  前端来解决跨域问题有几种方法:

  1、使用WebSocket通信协议,这里不详解。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

  2、中间代理服务转发:在前端服务和后端接口服务之间架设一个中间代理服务,它的地址保持和后端服务器一致,这样,我们就可以通过中间服务做接口转发,在开发环境下解决跨域问题。我们需要vue.config.js中配置代理服务,通过这个代理服务发送请求,由于代理服务和后端端口号相同,这样就不存在跨域的问题了,代码如下:

'use strict'
module.exports = {
    dev: {
        host: 'localhost',
        port: 8081,
        autoOpenBrowser: false,
        overlay: {
            warnings: false,
            errors: true
        },
        // 代理配置
        proxy: {
            // 如果请求地址以/data打头,就触发代理机制
            // http://localhost:8081/data/put/string -> http://localhost:8181/data/put/string
            '/data': {
                target: 'http://localhost:8181',//后端接口地址
                changeOrigin: true,//是否允许更改Origin
                pathRewrite: {
                    '^/data': '/data',//重写,
                }
            }
        },
    },
}
目录
相关文章
|
12天前
|
XML Java 数据格式
SpringBoot入门(8) - 开发中还有哪些常用注解
SpringBoot入门(8) - 开发中还有哪些常用注解
30 0
|
22天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
97 62
|
20天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
38 2
|
19天前
|
JavaScript NoSQL Java
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
32 0
|
23天前
|
JavaScript 前端开发 Java
SpringBoot_web开发-webjars&静态资源映射规则
https://www.91chuli.com/ 举例:jquery前端框架
17 0
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
152 1
|
2月前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的服装商城管理系统
基于Java+Springboot+Vue开发的服装商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的服装商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
155 2
基于Java+Springboot+Vue开发的服装商城管理系统
|
2月前
|
前端开发 JavaScript Java
SpringBoot项目部署打包好的React、Vue项目刷新报错404
本文讨论了在SpringBoot项目中部署React或Vue打包好的前端项目时,刷新页面导致404错误的问题,并提供了两种解决方案:一是在SpringBoot启动类中配置错误页面重定向到index.html,二是将前端路由改为hash模式以避免刷新问题。
241 1
|
23天前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
下一篇
无影云桌面