首页 > 其他分享 >跨域问题和解决方式

跨域问题和解决方式

时间:2023-05-07 17:55:37浏览次数:41  
标签:Control Origin 浏览器 跨域 方式 Access 解决 请求

一、同源策略和跨域

同源策略是一种约定,它是浏览器最核心也最基本的安全功能。

同源是指"协议+域名+端口"三者都要相同,当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。

二、跨域产生的问题

同源策略会阻止一个域的javascript脚本和另外一个域进行交互,所以通过ajax请求去获取另一个域的内容响应会被浏览器阻止进而失败。注意跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。Cookie、LocalStorage 、SessionStorage在不同域之间也是相互独立的。

但需要注意有三个标签在加载资源时是不受同源策略限制的

img,link,script这三个标签。

三、跨域问题的解决方式

3.1 jsonp

jsonp利用了script标签不受同源策略限制来进行跨域访问,它只支持get请求,并且需要服务端做处理来支持,jquery提供了发起jsonp请求的方式。

3.2 CORS

CORS是一个W3C标准,全称是"跨域资源共享" ,它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS需要浏览器和服务器同时支持。目前,主流浏览器都支持该功能所以仅需要在服务端添加一些CORS相关的请求头。

3.2.1 CORS相关概念

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(预检请求)

简单请求需要同时满足两个条件:

(1) 请求方式只能是HEAD,GET,POST

(2)只能携带这几种请求头:

Accept

Accept-Language

Content-Language

Last-Event-ID

Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain ,

这个条件可以简单记成只要我们想添加一些自定义的请求头时发出的就不是简单请求了。

跨域时浏览器对这两种请求的处理方式是不一样的

3.2.2 简单请求跨域

对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中自动增加一个Origin字段来说明本次请求来自哪个源。服务器会根据这个值决定是否允许本次访问。

如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应 ,浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出跨域访问的错误。

如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段

Access-Control-Allow-Origin: http://www.a.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Authorization

(1) Access-Control-Allow-Origin

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

(2) Access-Control-Allow-Credentials

该字段可选,它的值是一个布尔值,表示跨域访问是否允许发送Cookie ,默认是false,需要发送cookie时把该字段指定成true,

这是服务端的设置,同时前端也需要允许携带cookie,如使用ajax时要带上这个属性 withCredentials:true

(3) Access-Control-Expose-Headers

可选字段,CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本响应字段,也不需要记都有哪些,如果我们想获取到自定义的一些响应头就得在这个属性上指定,多个用逗号隔开。

所以前端发出简单请求时后端要做的就是根据Origin字段判断是否允许访问然后设置上边这几个响应头。

3.2.3 非简单请求跨域

简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight) 。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP请求方式和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错 。

预检"请求用的请求方式是OPTIONS,表示这个请求是用来询问的。头信息里面,关键字段是Origin,表示请求来自哪个源。 下面是一个预检请求的请求头示例

OPTIONS /cors HTTP/1.1
Origin: http://www.a.com
Access-Control-Request-Method: PUT  像服务器说明请求方式
Access-Control-Request-Headers: X-Custom-Header 像服务器说明会额外发送的请求头,多个以逗号隔开

上边这些操作都是浏览器自动完成的,所以前端不需要特殊处理。

服务器收到"预检"请求以后,检查了OriginAccess-Control-Request-MethodAccess-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。 回应中也会包含Access-Control-Allow-xxx

这种响应头,如果不允许访问就不包含这些请求头

Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers

"预检"请求通过后浏览器就会发出真正的请求进行通讯。上边服务器对请求头的这些处理还是相对比较麻烦的,但如果我们是一个使用了springmvc的项目,springmvc已经提供了一个过滤器,我们只需要做简单的配置就可以实现cors

3.2.4 springmvc中使用CORS

springmvc提供了一个CorsFilter可以用来处理cors,只需要把这个过滤器注册到我们的应用中,这里以springboot工程来举例,在配置类注册如下的bean

    //注册处理跨域的过滤器
    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
        FilterRegistrationBean<CorsFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        //创建跨域配置
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedMethod("GET");
        corsConfiguration.addAllowedMethod("POST");
        corsConfiguration.setAllowCredentials(false);

        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        //注册路径和对应的配置,
        //注意这个方法可以被多次调用,即可以给不同的路径设定不同的跨域配置
        corsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);
        CorsFilter corsFilter = new CorsFilter(corsConfigurationSource);
        filterRegistrationBean.setOrder(0);
        filterRegistrationBean.setFilter(corsFilter);
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }

3.3 使用代理

跨域问题只在浏览器中用js访问其它域时出现,服务器之间相互调用是不受限制的,所以可以A域对B域的访问可以在中间使用一个代理服务,A--->A的代理--->B ,这样对浏览器来说A和A的代理是同一个域的就不会有跨域问题。

这种方式不需要服务端做适配就能实现跨域访问。

具体的实现方式有vue自带的proxyTable,nginx反向代理,可以参考这篇文章vue+springboot前后端分离工程中跨域问题的解决

标签:Control,Origin,浏览器,跨域,方式,Access,解决,请求
From: https://www.cnblogs.com/chengxuxiaoyuan/p/17379683.html

相关文章

  • MSBulid编译器过程出现“lc.exe已退出,代码为-1“的解决方案
    这几天在查看winform旧项目的时候,发现编译过程中会出现“lc.exe已退出,代码为-1”的错误提示,导致程序无法正确编译,在网上查了一下,最后找到解决方法。因为项目使用了Developer第三方库功能,其在组件的使用类定义了LicenseProvider(typeof(LicFileLicenseProvider))这个Attribute。......
  • 远程桌面遇到的问题【解决参考】
    1、RemoteDesktopServices服务灰色无法启动“Win+R”打开运行,键入:services.msc,打开服务界面,找到“RemoteDesktopServices”服务,双击打开,确认服务名称为“TermService”;在打开“管理员:命令提示符”,键入以下命令查看当前“RemoteDesktopServices”服务对应的PID。命令:scqu......
  • MultiDex使用方法及由此导致的crash、ANR问题解决方案
    Android开发的朋友,如果是在开发一款中大型应用时,都会碰到这么一个问题,就是dex分拆问题,google给出的解决方案MultiDex。现象:有些APP本身功能比较多,再加上一些其它三方的SDK,慢慢的发现dex越来越大,直到有一天编译出现如下错误:Error:Thenumberofmethodreferencesina.dexfile......
  • 十二代酷睿处理器N100 N200 N305 等安装ESXI紫屏问题解决办法
    12代大小核紫屏报错解决方案四部曲1、安装界面倒计时结束之前,按SHIFT+O,在原有命令后面加空格后输入以下代码cpuUniformityHardCheckPanic=FALSE2、安装完ESXI之后会重启,在重启界面倒计时结束前,再操作一次,按住SHIFT+O,输入cpuUniformityHardCheckPanic=FALSE3、进入ESXI把SSH功能......
  • zabbix基于api方式批量创建监控项和触发器示例
    基于python3zabbixapi方式,达到批量创建指定机器业务端口的监控项和触发器的创建的效果,目前不支持并发处理,只支持串行处理zabbix-net-server.py内容,放到zabbix服务器上,然后执行python3 zabbix-net-server.py启动socket监听#!/usr/bin/python3importsocket,sys,timeimport......
  • 解决微信小程序请"注意游客模式下,调用 wx.login 是受限的, API 的返回是工具的模拟返
    新建一个微信小程序的项目,导入了代码后,出现微信小程序请"注意游客模式下,调用wx.login是受限的,API的返回是工具的模拟返回"这是因为,微信开发者工具没有配置小程序的appid下面添加上就可以了 ......
  • 解决微信小程序"不在以下 request 合法域名列表中"
    如果在本地开发的状态下,我们本机的地址域名是没有配置在小程序后台的我们可以临时禁用掉这个检测看下面图示 ......
  • 关于vue系统禁止脚本运行问题的解决
    问题描述满怀期待地输入vuelist命令行,然后就出现了这个错误问题解决以管理员身份运行终端界面,在该界面输入get-ExecutionPolicy,查看脚本运行状态是否被允许,若是出现Restricted结果,则表明被禁止;若是出现RemoteSigned结果,则表明没有被禁止;(是可以正常使用的!)若是被禁止,则输入se......
  • k01_idea解决超过三十天无法登录问题
    idea过期问题当IDEA过期了无法进入程序的时候我们大可不必卸载重新安装只需要删除指定文件即可!1、寻找目录如:C:\Users\zhangsan(您的主机目录)\AppData\Roaming\JetBrains\IntelliJIdea2020.1\eval2、删除文件删除指定的那个文件即可!对于不同的idea版本号会不同!根据实际情况删......
  • 下端下载文件几种方式
    一、a标签download下载后端返回一个可下载的url文件,或者前端本地保存的文件,通过路径引入下载。(1)将资源放入前端本地保存,打包后随一起上传自服务器//本地资源下载,引入路径即可,这里的路径指的是打包后文件与代码文件的相对路径<ahref="./import-template.xlsx"downloadtarget=......