SpringBoot3解决跨域请求问题(同源策略、JSONP、CORS策略)(Access-Control-Allow-Origin)(2025详细教程)

目录

浏览器跨域请求问题。

浏览器同源策略。

第三方API调用。

前后端分离项目。

一、JSONP。(dataType:'jsonp')

(1)代码示例。

<1>前端ajax04.jsp页面。(发起Ajax请求)

<2>后端springboot接口。(/hello)(返回JSONPObject对象)

(2)使用"JSONP"时注意事项。

Cross-Origin Resource Sharing策略。(跨域资源共享)

(1)基本介绍。

(2)基本工作原理。(Access-Control-Allow-Origin)

二、注解@CorssMapping。(用在控制器类或方法)

(1)代码示例。

<1>前端ajax.jsp页面。(发起Ajax请求)

<2>后端控制器类。("/employee/selectById")(注解@CrossOrigin)

三、SpringBoot3中自定义跨域请求与配置。(处理跨域拦截)

(1)实现接口WebMvcConfigurer。(配置类@Configuration)

<1>重写addCorsMapping()方法。

<2>Vue3页面中的Ajax请求。(async)

test02.vue页面代码。

test02.vue页面路由配置。

封装request、response的js文件。

<3>点击按钮,触发绑定事件(请求),页面渲染效果。

(2)配置CorsFilter对象并加入IoC容器(@Bean)。(全局的CORS配置)

<1>后端配置类。(CorsConfig跨资源共享配置类)(返回CorsFilter跨资源共享拦截器对象)


  • 浏览器跨域请求问题。

  • 浏览器同源策略。
  • 浏览器的同源策略是一种重要的安全机制,用于限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。
  • 浏览器同源策略的主要目的:防止恶意网站窃取用户的敏感信息。如果没有同源策略,恶意网站可以通过脚本读取用户访问过的其他网站的内容、发送请求等,从而获取用户的登录凭证、个人信息等。

  • 第三方API调用。
  • 当网页需要调用第三方提供的 API 时,由于第三方 API 的域名与当前网页的域名不同,会产生跨域请求。如网页中集成了地图服务,需要调用百度地图的API来获取地图数据和相关功能,而百度地图API的域名与网页所在域名不同,就会触发跨域请求。

  • 前后端分离项目。
  • 通常在Web开发中,很多项目采用前后端分离的架构。前端代码部署在一个域名下,而后端 API 服务部署在另一个域名下。此时当浏览器从前端页面向后端API发送请求时,就会发生跨域请求。

  • 前端工程部署在本地:http://localhost:5173/


  • 后端工程部署在本地:http://localhost:9090/


  • 因浏览器的同源策略导致前端发起的请求被阻止。

一、JSONP。(dataType:'jsonp')

  • 用于解决跨域的Ajax请求的一种方式。(不常用)
(1)代码示例。
<1>前端ajax04.jsp页面。(发起Ajax请求)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>ajax请求</title><%--引入jquery--%><script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
<button onclick="myFunction()">调用接口:/hello</button>
<script>function myFunction() {$.ajax({url:"http://localhost:9090/hello",type:"GET",dataType:"jsonp",success:function (data){console.log(data)}})}
</script>
</body>
</html>




<2>后端springboot接口。(/hello)(返回JSONPObject对象)
package com.hyl.controller;import com.fasterxml.jackson.databind.util.JSONPObject;
import com.hyl.common.Result;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;//表示对外提供可访问接口的类
@RestController
public class WebController {//测试接口@GetMapping("/hello")public JSONPObject hello(String callback){return new JSONPObject(callback,Result.success("hello"));}}
 

package com.hyl.common;/*** 统一后端返回的数据结果类型*/
public class Result {//请求状态码private String code;//成功或错误信息private String msg;//返回数据结果private Object data;//常用静态方法//请求成功且无数据返回public static Result success(){Result result = new Result();result.setCode("200");result.setMsg("请求成功");return result;}//请求成功且有数据返回。public static Result success(Object data) {//直接调用静态方法设置状态码、请求成功信息Result result = Result.success();result.setData(data);return result;}//请求失败且无数据返回public static Result error(){Result result = new Result();result.setCode("500");result.setMsg("系统出错了!");return result;}//请求失败且无数据返回。适配自定义异常(传递code、msg)public static Result error(String code,String msg){Result result = new Result();result.setCode(code);result.setMsg(msg);return result;}//getter、setter方法public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}
}

(2)使用"JSONP"时注意事项。
  • 许多浏览器不兼容问题。(该方法不常用)
  • 后端必须返回JSONPObject对象。大量使用耦合度高。

  • 综上:对于"JSONP"方式使用大概了解与能够简单使用就行,不需要深度学习。
  • Cross-Origin Resource Sharing策略。(跨域资源共享)

(1)基本介绍。
  •  CORS是一种基于 HTTP头的机制,它允许 Web应用程序从不同源(域名、协议、端口)请求和访问资源,克服了浏览器的同源策略限制。
(2)基本工作原理。(Access-Control-Allow-Origin)
  • 1、浏览器在发送跨域请求时,会先发送一个预检请求,以询问服务器是否允许该跨域请求。
  • 2、服务器收到预检请求后,会检查请求头中的相关信息,如Origin(表示请求的源),并根据自身的CORS配置返回相应的响应头。
  • 3、如果服务器允许该请求,会在响应头中包含Access-Control-Allow-Origin等字段,告知浏览器该请求的源是被允许的。浏览器接收到允许跨域的响应后,才会发送实际的请求。

  • 如下面控制台报错未在响应头中告诉浏览器所需字段。就受到了浏览器同源策略限制。

二、注解@CorssMapping。(用在控制器类或方法)

(1)代码示例。
<1>前端ajax.jsp页面。(发起Ajax请求)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>ajax请求</title><%--引入jquery--%><script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
<button onclick="myFunction()">调用接口:/employee/selectById/{id}</button>
<script>let id = 1; //测试请求id为1的员工信息function myFunction() {$.ajax({url:"http://localhost:9090/employee/selectById/"+ id,type:"GET",dataType:"json",success:function (data){alert('请求状态码:'+data.code+'\n请求消息:'+data.msg+'\n请求数据:'+JSON.stringify(data.data))console.log("根据Id获取员工信息:"+JSON.stringify(data.data))}})}
</script>
</body>
</html>


<2>后端控制器类。("/employee/selectById")(注解@CrossOrigin)
package com.hyl.controller;import com.hyl.common.Result;
import com.hyl.entity.Employee;
import com.hyl.service.EmployeeService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("/employee")
public class EmployeeController {@Resourceprivate EmployeeService employeeService;/***根据id查询员工*/@GetMapping("/selectById/{id}")@CrossOrigin("http://localhost:8080/")public Result selectById(@PathVariable Integer id){Employee employee = employeeService.selectById(id);return Result.success(employee);}}

  • 请求成功。结果如下。

三、SpringBoot3中自定义跨域请求与配置。(处理跨域拦截)

(1)实现接口WebMvcConfigurer。(配置类@Configuration)


<1>重写addCorsMapping()方法。
  • 后端配置类。
package com.hyl.common;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;@Configuration
public class CorsConfig02 implements WebMvcConfigurer {// 处理跨域请求@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**")/*.allowedOrigins("*") //允许所有源的跨域请求*//*.allowedOriginPatterns("http://localhost:5173/") //指定允许的源模式*/.allowedOriginPatterns("http://localhost*") //指定允许的源模式.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的方法.allowedHeaders("*") // 允许的请求头.allowCredentials(true) // 允许携带凭证.maxAge(3600); // 预检请求的缓存时间}}

<2>Vue3页面中的Ajax请求。(async)
  • test02.vue页面代码。
<template><div style="margin: 30px"><h3>测试Ajax请求后端接口"/selectById/{id}"</h3><el-button type="success" @click="testAjax(data.id)">发起请求 获取数据</el-button><div style="margin: 15px;"><span>请求数据:{{data.employee}}</span></div><div style="margin: 15px;"><span>请求状态码:{{data.code}}</span></div></div>
</template><script setup>
import {reactive} from "vue";
import request from "@/utils/request.js";const data = reactive({employee:null,id:1, //假定测试请求id=1的员工信息code:null,
})const testAjax = async (id) =>{try {const response = await request.get("/employee/selectById/" + id);data.employee = response.datadata.code = response.code} catch (e) {console.error(e)}
}</script><style scoped></style>
  • test02.vue页面路由配置。
import { createRouter, createWebHistory } from 'vue-router'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path:'/',redirect:'/manager/home'},{path:'/manager',meta:{ title:'父级页面'},component: () => import('../views/Manager.vue'),children:[{path: 'home', name: 'home', meta:{ title:'主页'}, component: () => import('../views/Home.vue')}, // url:/manager/home{path: 'test', name: 'test', meta:{ title:'测试数据页01'},  component: () => import('../views/Test.vue')}, // url:/manager/test{path: 'demo', name: 'demo', meta:{ title:'测试数据页02'},  component: () => import('../views/Demo.vue')}, // url:/manager/demo{path: 'data', name: 'data', meta:{ title:'数据展示页面'},  component: () => import('../views/Data.vue')}, // url:/manager/data{path: 'employee', name: 'employee', meta:{ title:'员工信息页面'},  component: () => import('../views/Employee.vue')}, // url:/manager/employee{path: 'test02', name: 'test02', meta:{ title:'测试Ajax请求'},  component: () => import('../views/Test02.vue')}, // url:/manager/test02]},{path: '/login', name: 'login', meta:{ title:'登录页面'}, component: () => import('../views/Login.vue')},{path: '/register', name: 'register', meta:{ title:'欢迎注册'}, component: () => import('../views/Register.vue')},{path: '/404', name: 'NotFound', meta:{ title:'404找不到页面'}, component: () => import('../views/404.vue')},{path:'/:pathMatch(.*)',redirect:'/404'}],
})router.beforeEach((to,from,next)=>{//设置即将跳转的路由页面的网页标题document.title=to.meta.titlenext() //必须调用的方法
})export default router
  • 封装request、response的js文件。
import { ElMessage } from 'element-plus'
import axios from "axios";const request = axios.create({//设置后台请求地址baseURL: 'http://localhost:9090',timeout: 30000  // 后台接口超时时间设置
})// request 拦截器(数据请求)
// 可以自请求发送前对请求做一些处理
request.interceptors.request.use(config => {//设置统一的数据传输格式json、数据传输编码utf-8config.headers['Content-Type'] = 'application/json;charset=utf-8';return config
}, error => {return Promise.reject(error)
});// response 拦截器
// 可以在接口响应后统一处理结果
request.interceptors.response.use(response => {//响应对象response中提取实际数据部分,存储在变量res中let res = response.data;// 兼容服务端返回的字符串数据//如果res是字符串且不为空字符串,则使用JSON.parse方法将其解析为JavaScript对象;//如果 res 为空字符串,则保持原样。if (typeof res === 'string') {res = res ? JSON.parse(res) : res}return res;},error => {if(error.response.status === 404){//404 状态码表示请求的资源未找到,通常意味着请求的接口不存在ElMessage.error('未找到请求接口')}else if(error.response.status === 500){//500:之前后端设置的全局系统异常处理捕获//500 状态码表示服务器内部错误,通常是由于后端代码出现异常ElMessage.error('系统异常,请查看后端控制台报错')}else{//其它情况统一打印错误信息console.error(error.message)}//将错误继续抛出,以便后续的代码可以继续处理该错误return Promise.reject(error)}
)export default request

<3>点击按钮,触发绑定事件(请求),页面渲染效果。
  • 未点击按钮时。


  • 点击按钮。请求指定接口并获取数据渲染页面。

(2)配置CorsFilter对象并加入IoC容器(@Bean)。(全局的CORS配置)


<1>后端配置类。(CorsConfig跨资源共享配置类)(返回CorsFilter跨资源共享拦截器对象)
package com.hyl.common;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 让该配置类注入到Spring容器中并能够扫描到其下类下注解*/
@Configuration
public class CorsConfig {/*** 创建并注册CorsFilter bean,用于处理跨域请求* @return CorsFilter实例,Spring会在请求处理过程中使用该过滤器处理跨域请求* @Bean 注解会让该方法的返回值注入到Spring容器中*/@Beanpublic CorsFilter corsFilter() {// 创建一个基于URL的跨域配置源对象,用于存储和管理不同URL路径的跨域配置UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();// 创建一个跨域配置对象,用于设置具体跨域规则CorsConfiguration corsConfiguration = new CorsConfiguration();// 设置允许访问的源地址,这里使用通配符"*",表示允许所有源地址访问corsConfiguration.addAllowedOrigin("*");// 设置允许的请求头,"*"表示允许所有请求头,即前端可以在请求中携带任意请求头corsConfiguration.addAllowedHeader("*");// 设置允许的请求方法,"*"表示允许所有的HTTP请求方法,如GET、POST、PUT、DELETE等corsConfiguration.addAllowedMethod("*");// 将跨域配置应用到所有的接口路径上,"/**"表示匹配所有路径source.registerCorsConfiguration("/**", corsConfiguration);// 创建并返回CorsFilter实例,传入配置源对象,Spring会使用该过滤器处理跨域请求return new CorsFilter(source);}
}

  • 前端Vue页面(localhost:5173)请求后端springboot服务器(localhost:9090)。页面渲染效果如下。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/42562.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rent8_wechat-新增提醒收租功能

本次更新中&#xff0c;rent8_wechat 小程序全新推出了“提醒收租”功能&#xff0c;为房东提供更加便捷的收租体验。房东只需在小程序内点击“提醒收租”按钮&#xff0c;系统便会在需要收租当天的上午9点准时推送通知&#xff0c;贴心提醒房东及时收取租金。 以下是该功能的…

诠视科技MR眼镜如何安装apk应用

诠视科技MR眼镜如何安装apk应用 1、使用adb工具安装1.1 adb工具下载1.2 解压adb文件1.3 使用adb安装apk 2、拷贝到文件夹安装 1、使用adb工具安装 1.1 adb工具下载 点击下面的链接开始下载adb工具&#xff0c;下载结束以后解压文件。 下载链接: https://download.xvisiotech…

JAVA学习*异常

什么是异常 在 Java 里&#xff0c;异常是指程序运行期间出现的不正常状况&#xff0c;它会中断程序的正常执行流程。 异常的分类 Java 中的异常是对象&#xff0c;这些对象都继承自 Throwable类。Throwable类有两个主要的子类&#xff1a;Error 和 Exception。 Error类表示…

DataGear 5.3.0 制作支持导出表格数据的数据可视化看板

DataGear 内置表格图表底层采用的是DataTable表格组件&#xff0c;默认并未引入导出数据的JS支持库&#xff0c;如果有导出表格数据需求&#xff0c;则可以在看板中引入导出相关JS支持库&#xff0c;制作具有导出CSV、Excel、PDF功能的表格数据看板。 在新发布的5.3.0版本中&a…

【电气设计】接地/浮地设计

在工作的过程中&#xff0c;遇到了需要测量接地阻抗的情况&#xff0c;组内讨论提到了保护接地和功能接地的相关需求。此文章用来记录这个过程的学习和感悟。 人体触电的原理&#xff1a; 可以看到我们形成了电流回路&#xff0c;导致触电。因此我们需要针对设备做一些保护设计…

【计算机操作系统】线程的概念和特点

1、什么是线程&#xff0c;为什么要引入线程&#xff1f; 还没引入进程之前&#xff0c;系统中各个程序只能串行执行。 比如&#xff1a;当我们在使用QQ与好友视频时&#xff0c;我们可以给其他好友发信息&#xff0c;发送文件...&#xff0c;我们知道进程是程序的一次执行&am…

【C++数据库】SQLite3数据库连接与操作

注意:本文代码均为C++20标准下实现 一、SQLite3库安装 1.1 安装库文件 【工具】跨平台C++包管理利器vcpkg完全指南 vcpkg install sqlite3# 集成至系统目录,之前执行过此命令的无需再次执行 vcpkg integrate install1.2 验证代码 在VS2022中新建控制台项目,测试代码如下…

CLion下载安装(Windows11)

目录 CLion工具下载安装其他 CLion CLion-2024.1.4.exe 工具 系统&#xff1a;Windows 11 下载 1.通过百度网盘分享的文件&#xff1a;CLion-2024.1.4.exe 链接&#xff1a;https://pan.baidu.com/s/1-zH0rZPCZtQ60IqdHA7Cew?pwdux5a 提取码&#xff1a;ux5a 安装 打开…

‘无法定位程序输入点kernel32.dll’详细的修复方法,一键快速修复kernel32.dll

在 Windows 系统运行过程中&#xff0c;若程序提示“无法定位程序输入点 kernel32.dll”&#xff0c;往往意味着程序调用了 kernel32.dll 中不存在或已变更的函数接口。作为系统的核心动态链接库&#xff0c;kernel32.dll 承担着内存管理、进程控制、文件操作等底层功能&#x…

二层综合实验

拓扑图 实验要求 1.内网IP地址使用172.16.6.0/16分配 2.sw1和sW2之间互为备份 3.VRRP/STP/VLAN/Eth-trunk均使用 4.所有Pc均通过DHCP获取IP地址 5.ISP只能配置IP地址 6.所有电脑可以正常访问IsP路由器环回 实验思路 这是一个二层综合实验每当拿到一个实验看清楚要求之后都有…

PS 切割图片

选择矩形工具绘制矩形 选中全部矩形&#xff0c;旋转一下角度 鼠标选中最下面的黄色图片&#xff0c;按住 Ctrl 键&#xff0c; 再用鼠标点击矩形的缩略图&#xff0c;选中选区&#xff0c;再按下 ctrlj &#xff0c;复制选区。 同样操作弄好其他的矩形选区&#xff0c;再删除…

项目管理证书 PMP 的含金量高吗?

一、国内PMP的含金量 1. 行业认可度 高需求行业&#xff1a;IT、通信、建筑、制造、金融等行业对PMP认可度较高&#xff0c;尤其是跨国企业、大型国企&#xff08;如华为、阿里、腾讯、中建等&#xff09;常将PMP作为项目经理岗位的优先录用条件。 招聘门槛&#xff1a;部分企…

旅游CMS选型:WordPress、Joomla与Drupal对比

内容概要 在旅游行业数字化转型进程中&#xff0c;内容管理系统&#xff08;CMS&#xff09;的选择直接影响网站运营效率与用户体验。WordPress、Joomla和Drupal作为全球主流的开源CMS平台&#xff0c;其功能特性与行业适配性存在显著差异。本文将从旅游企业核心需求出发&…

LeetCode349两个数组的交集

思路&#xff1a; 这个题目是查找交集&#xff0c;考虑用哈希数组&#xff0c;c语言用数组建立哈希表来解题&#xff0c;题目限定了数组长度在1000以内&#xff0c;那么可以设定一个result数组用于存储交集 1.我们需要将nums1映射到哈希表中 2.遍历nums2查询哈希表中是否存在该…

安装教程:windows上安装oracle详细教程

文章目录 前言一、下载 Oracle 安装包二、安装步骤三、连接ORACLE可视化工具1.1 PL/SQL Developer1.2 navicat 结束语优质源码分享 windows上安装oracle详细教程&#xff0c;在Windows上安装Oracle数据库需遵循以下步骤&#xff1a;首先&#xff0c;从官网下载对应版本的Oracle…

4、网工软考—VLAN配置—hybird配置

1、实验环境搭建&#xff1a; 2、实验过程 SW1&#xff1a; 先创建vlan2和vlan3 [Huawei-Ethernet0/0/2]port link-type hybrid //hybird端口 [Huawei-Ethernet0/0/2]port hybrid pvid vlan 2 [Huawei-Ethernet0/0/2]port hybrid untagged vlan 10 //撕掉vlan10的标签 …

平台清洗行动:AI浏览器用户生存率高出传统方案17倍

平台清洗行动&#xff1a;AI 浏览器用户生存率高出传统方案 17 倍 在这个数字化时代&#xff0c;网络环境的复杂性不断增加&#xff0c;用户在浏览网页时面临着各种风险&#xff0c;包括恶意软件、钓鱼攻击和隐私泄露等。为了应对这些挑战&#xff0c;AI 浏览器应运而生&#…

【C++篇】C++入门基础(一)

&#x1f4ac; 欢迎讨论&#xff1a;在阅读过程中有任何疑问&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;如果你觉得这篇文章对你有帮助&#xff0c;记得点赞、收藏&#xff0c;并分享给更多对C感兴趣的…

MaskFormer语义分割算法测试

MaskFormer是一套基于transformer结构的语义分割代码。 链接地址&#xff1a; https://github.com/facebookresearch/MaskFormer/tree/main 测试用的数据集&#xff1a;ADE20k Dataset MIT Scene Parsing Benchmark 该数据集可通过上述链接下载&#xff0c;其中training含有…

javaWeb vue的简单语法

一、简介 两大核心优势&#xff1a; 声明式渲染&#xff1a;Vue 基于标准 HTML 拓展了一套模板语法&#xff0c;使得我们可以声明式地描述最终输出的 HTML 和 JavaScript 状态之间的关系。 响应性&#xff1a;Vue 会自动跟踪 JavaScript 状态并在其发生变化时响应式地更新 D…