文章目录

  • 一、为什么会出现跨域问题
  • 二、什么是跨域
  • 三、非同源限制
  • 四、跨域问题的解决方式
    • Jsonp前后端配合
      • 前端修改
      • 后端修改
    • CORS
      • 详解响应头
  • 5. SpringBoot解决
    • 【方式一】全局配置
    • 【方式二】@CrossOrigin
    • Nginx反向代理解决跨域问题

一、为什么会出现跨域问题

由于浏览器的同源策略限制

同源策略(Same-Origin-Policy)是一种约定,它是浏览器最核心、最基本的安全功能。如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的JavasSript脚本和另外一个域的内容进行交互。

同源(即指在同一个域):两个页面具有相同的协议(protocol),主机(host)和端口号(port)

  • 协议相同
  • 域名相同
  • 端口相同

浏览器执行JavaScript脚本时,会检查这个脚本属于哪个页面,如果不是同源页面,就不会被执行.

服务器之间的请求是不存在跨域问题的!

【明确因果】有浏览器存在,才会产生跨域问题。而浏览器浏览器最核心、最基本的安全功能是同源策略。基于这种策略下,不予许访问非访问非同源的资源(即跨域请求)

二、什么是跨域

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

当前页面url 被请求页面url 是否跨域 原因
http://www.test.com/ http://www.test.com/index.html 同源(协议、域名、端口号相同)
http://www.test.com/ https://www.test.com/index.html 跨域 协议不同(http/https)
http://www.test.com/ http://www.baidu.com/ 跨域 主域名不同(test/baidu)
http://www.test.com/ http://blog.test.com/ 跨域 子域名不同(www/blog)
http://www.test.com:8080/ http://www.test.com:7001/ 跨域 端口号不同(8080/7001)

请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域.

例如:

  • 在本站点上请求本站点的资源,不会报错
  • 在本站点上请求其他站点的资源,报错(在Google上请求百度的资源)

【报错信息】Access to fetch at ‘https://www.baidu.com/’ from origin ‘https://www.google.com’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.

三、非同源限制

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

【2】无法接触非同源网页的 DOM

【3】无法向非同源地址发送 AJAX 请求

四、跨域问题的解决方式

Jsonp前后端配合

JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE)

【缺点】

  • 只支持get请求,不支持post请求
  • 只支持跨域HTTP请求

<script>标签是天然支持跨域的,我们通过<script>标签可引入外部的脚本,即请求别的资源

【核心思想】

网页通过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。

前端修改

①原生实现:

// 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
<script src="http://test.com/data.php?callback=dosomething"></script>// 处理服务器返回回调函数的数据
<script type="text/javascript">function dosomething(res){// 处理获得的数据console.log(res.data)}
</script>

② jQuery ajax:

$.ajax({url: 'http://www.test.com:8080/login',type: 'get',dataType: 'jsonp',  // 请求方式为jsonpjsonpCallback: "handleCallback",    // 自定义回调函数名data: {}
});

③ Vue.js

this.$http.jsonp('http://www.domain2.com:8080/login', {params: {},jsonp: 'handleCallback'
}).then((res) => {console.log(res);
})

后端修改

服务端不在返回的是一个JSON格式的数据,而是返回一段JS代码,将JSON的数据以参数的形式传递到这个函数中,而函数的名称就是callback参数的值。

将JS对象解析成JSON,再传入调用函数。

Jsonp虽然有效,但是处理具有局限性。我们一般都采用CORS


CORS

CORS是一种W3C标准,全称是"跨域资源共享(Cross-origin resource sharing)"。它允许浏览器向跨源服务器发出XMLHttpRequest请求,从而克服了同源使用的限制。

实现CORS很简单,就是在服务端加一些响应头,对前端来说是无感知的。

详解响应头

Access-Control-Allow-Origin

  • 该字段必填
  • 它的值要么是请求时Origin字段的具体值,要么是一个*,表示接受任意域名的请求。

Access-Control-Allow-Methods

  • 该字段必填
  • 它的值是逗号分隔的一个具体的字符串或者*,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

Access-Control-Expose-Headers

  • 该字段可选
  • CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。

Access-Control-Allow-Credentials

  • 该字段可选
  • 它的值是一个布尔值,表示是否允许发送Cookie.默认情况下,不发生Cookie,即:false。对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json,这个值只能设为true。如果服务器不要浏览器发送Cookie,删除该字段即可。

Access-Control-Max-Age

  • 该字段可选
  • 用来指定本次预检请求的有效期,单位为秒。在有效期间,不用发出另一条预检请求。

下面,我们使用CROS通过SpringBoot来在解决后端跨域问题


5. SpringBoot解决

【方式一】全局配置

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 {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**") // 所有的当前站点的请求地址,都支持跨域访问.allowedOrigins("*") // 所有的外部域都可跨域访问。 如果是localhost则很难配置,因为在跨域请求的时候,外部域的解析可能是localhost、127.0.0.1、主机名.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS") // 当前站点支持的跨域请求类型是什么.allowCredentials(true) // 是否支持跨域用户凭证.maxAge(3600) // 超时时长设置为1小时。 时间单位是秒。.allowedHeaders("*"); //获取所有请求头字段}
}

WebMvcConfigurerAdapter在Spring5.0已经被标记为Deprecated,推荐使用过滤器

基于过滤器的方式,方式简单明了,就是在response中写入这些响应头

import org.springframework.context.annotation.Configuration;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebFilter(filterName = "CorsFilter ")
@Configuration
public class CorsFilter implements Filter {@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {HttpServletResponse response = (HttpServletResponse) res;response.setHeader("Access-Control-Allow-Origin","*");response.setHeader("Access-Control-Allow-Credentials", "true");response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");response.setHeader("Access-Control-Max-Age", "3600");response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");chain.doFilter(req, res);}
}

【方式二】@CrossOrigin

@CrossOrigin细粒度单个请求控制

public class GoodsController {@CrossOrigin(origins = "http://localhost:8181")@GetMapping("/list")public Response queryGoodsWithGoodsUrl(@RequestParam String goodsUrl) throws Exception {}
}

@CrossOrigin注解,点开注解

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {}

从元注解@Target可以看出,注解可以放在method、class等上面,类似RequestMapping,也就是说,整个controller下面的方法可以都受控制,也可以单个方法受控制。

也可以得知,这个是最小粒度的CROS控制办法了,精确到单个请求级别。

Nginx反向代理解决跨域问题

跨域详解!前后端分离解决跨域问题相关推荐

  1. Vue flask前后端分离解决跨域

    Vue flask前后端分离解决跨域 安装axios 在项目目录下输入:npm install axios--save-dev 配置axios 在main.js中引入axios import axio ...

  2. vue解决线上跨域的问题_vue前后端分离解决跨域问题

    用Vue-cli脚手架搭建了个demo,前后分离就有跨域问题的出现. vue-clie搭建demo步骤(传送门):https://www.cnblogs.com/wangenbo/p/8487764. ...

  3. 解决java前后端分离端口跨域问题

    解决java前后端分离端口跨域问题 参考文章: (1)解决java前后端分离端口跨域问题 (2)https://www.cnblogs.com/mollie-x/p/10449686.html 备忘一 ...

  4. 前后端分离项目跨域问题及解决方案

    目录 1.什么是跨域 2.前后端分离项目中的跨域问题 3.方法一:SpringBoot后端进行处理 4.方法二:在Vue前端进行处理 5.总结 1.什么是跨域 请求同域资源: 在域名 (或 ip 地址 ...

  5. Vue+Flask前后端分离 Vue3跨域配置

    Vue+Flask前后端分离 Vue3跨域配置 前端端口号为8080 后端端口号为5000 问题描述 问题解决 接口路径映射 前端端口号为8080 后端端口号为5000 后端端口API 代码片. @a ...

  6. php 跨域 验证_php 前后端分离开发进行跨域请求时ajax发送验证参数token的header头解决方法...

    php前后端分离开发中要实现前后端参数信息交互,必须解决token标识验证问题. 步骤如下: 1.前端ajax发送请求时,要设置一个自定义header头.代码如下: $.ajax({ url:&quo ...

  7. Spring Boot2.x-13前后端分离的跨域问题解决方法之Nginx

    文章目录 概述 浏览器同源策略 后台搭建 pom.xml interceptor 配置 Controller 启动测试 浏览器和session 后端工程发布到服务器上 问题复现 通过Nginx反向代理 ...

  8. 前后端分离的跨域解决方案

    声明: 在以往的开发中,前后端分离也不是像现在这么热门,所谓的前端工程师也只不过是写好静态页面由Java工程师或者php工程师嵌入到页面中进行开发,这或许加重了这些工程师的工作量,而且在样式调试上由纯 ...

  9. cors 前后端分离跨域问题_前后端分离之CORS跨域访问踩坑总结

    前言 前后端分离的开发模式越来越流行,目前绝大多数的公司与项目都采取这种方式来开发,它的好处是前端可以只专注于页面实现,而后端则主要负责接口开发,前后端分工明确,彼此职责分离,不再高度耦合,但是由于这 ...

最新文章

  1. 让你轻松学会PHP版自动化SQL盲注工具-全库-全表-全字段-全字段值查询
  2. Apache引起的wampserver安装好第二次使用无法启动问题
  3. 在没有复杂插件的情况下从Eclipse启动和调试Tomcat
  4. mysql all_同样是MySQL的all privileges有啥不同?
  5. c++ 数组的输入遇到特定字符停止输入_C语言 第4章-字符串和格式化输入/输出
  6. mysql 消息队列_MYSQL模拟消息队列(转载) | 学步园
  7. 【题解】Luogu P5360 [SDOI2019]世界地图
  8. 【每日一练 088】性能优化-SQL tuning(一)
  9. 蜂鸣器驱动电路 自主开发设计
  10. 2022主流技术 Appium+IOS 自动化测试环境搭建
  11. 业务流程监控:让多维度监控有了灵魂
  12. 计算机字体对于现代设计有何意义,创意字体在现代设计中的重要性
  13. (2)ubuntu 中安装epics 的额外插件---asyn 以及 streamdevice
  14. 应用计算机测定线性电阻电路图和实物图,PC817中文数据摘要_PC817引脚图和功能_工作原理_特性参数及典型应用电路...
  15. 多功能的U盘启动盘制作工具
  16. 数值计算方法——matlab实现
  17. 独家!量子通信上市企业2020营收、净利润、研发费用排行榜
  18. 群晖NAS用迅雷远程下载Xware 1.xxx的进程监视和掉线自动重启
  19. 【完美解决】android开发 自定义字体安装包过大的问题
  20. 一阶低通滤波器方程_请教一阶二阶低通滤波器

热门文章

  1. c语言程序与设计期末考试,C语言程序设计期末考试卷A答案
  2. mysql 如何解决memory_解决memory
  3. 特劳特举办定位理论50周年全球盛典
  4. 对VR感兴趣,贾樟柯正在筹备VR电影长片
  5. 懒人听书:师父关于人们的奇怪之处之谈
  6. 华硕X450j清灰教程
  7. [iOS]Xcode4/iOS5调试UncaughtException崩溃First throw call stack不打印方法名的解决方案
  8. 新媒体人必备的4个热点数据分析工具,超实用
  9. mysql数据应用从入门_《MySQL数据库应用从入门到精通》
  10. 第二代计算机网络的贡献,在第二代计算机上,有操作系统支持其运行。