详解cors跨域的几种不同实现方式(代码片段)

zhaosq zhaosq     2022-12-03     608

关键词:

CORS 定义

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing),它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,是 JSONP 模式的现代版。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好。另一方面,JSONP 可以在不支持 CORS 的老旧浏览器上运作。现代的浏览器都支持 CORS。

CORS是W3c工作草案,它定义了在跨域访问资源时浏览器和服务器之间如何通信。CORS背后的基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否。W3C CORS 工作草案
同源策略:是浏览器最核心也最基本的安全功能;同源指的是:同协议,同域名和同端口。精髓:认为自任何站点装载的信赖内容是不安全的。当被浏览器半信半疑的脚本运行在沙箱时,它们应该只被允许访问来自同一站点的资源,而不是那些来自其它站点可能怀有恶意的资源;参考:JavaScript 的同源策略
JSON & JSONP:JSON 是一种基于文本的数据交换方式,或者叫做数据描述格式。JSONP是资料格式JSON的一种“使用模式”,可以让网页从别的网域要资料,由于同源策略,一般来说位于server1.example.com的网页无法与不是 server1.example.com的服务器沟通,而HTML的script元素是一个例外。利用script元素的这个开放策略,网页可以得到从其他来源动态产生的JSON资料,而这种使用模式就是所谓的JSONP

CORS 对比 JSONP

都能解决 Ajax直接请求普通文件存在跨域无权限访问的问题

  1. JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求
  2. 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理
  3. JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS

CORS,BROWSER支持情况

数据来源:caniuse.com

IE6,IE7,Opera min 不支持CORS。具体可参看数据来源中的 ‘show all‘

技术图片

主要用途

  • From a browser script perspective: By allowing cross-domain requests, which are subject to tighter controls on the types of data that is exchanged. Cookies, for instance, are blocked unless specifically requested by the XHR author and allowed by the cross-domain web service. This is done to mitigate the risk of data leaks.
  • From a web service perspective: By utilising the origin URL reported by the browser the target cross-domain web service can determine, based on its origin policy, whether to allow or deny the request.
  • 从浏览器脚本的角度来看:通过允许跨域请求,对交换的数据类型进行更严格的控制。例如,除非XHR作者特别要求并且跨域Web服务允许,否则将阻止cookie。这样做是为了降低数据泄漏的风险。
  • 从Web服务的角度来看:通过使用浏览器报告的源URL,目标跨域Web服务可以根据其源策略确定是否允许或拒绝请求。

Ajax请求跨域资源的异常

当出现如下异常时,那么就需要考虑跨域的问题了
例如 localhost:63343 通过Ajax请求http://192.168.10.61:8080服务器资源时就会出现如下异常:

技术图片

CORS 实现思路

CORS背后的基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否

安全说明

CORS is not about providing server-side security. The Origin request header is produced by the browser and the server has no direct means to verify it.

CORS 并不是为了解决服务端安全问题,而是为了解决如何跨域调用资源。至于如何设计出 安全的开放API,却是另一个问题了,这里提下一些思路:

  1. 请求时间有效性(验证timestamp与服务接到请求的时间相差是否在指定范围内,比如5分钟内)
  2. token验证
  3. ip验证
  4. 来源验证

例如

  ‘name‘: 用户名,

  ‘key: 加密的验证key,//(name+secret+timestamp来通过不可逆加密生成)

  ‘timestamp’: 时间戳,//验证timestamp与服务接到请求的时间相差是否在指定范围内,比如5分钟内

CORS 几种解决方案

CORS背后的基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否.

Access-Control-Allow-Origin:指定授权访问的域
Access-Control-Allow-Methods:授权请求的方法(GET, POST, PUT, DELETE,OPTIONS等)

一:简单的自定义CORSFilter / Interceptor

适合设置单一的(或全部)授权访问域,所有配置都是固定的,特简单。也没根据请求的类型做不同的处理

在web.xml 中添加filter

<filter>

    <filter-name>cros</filter-name>

    <filter-class>cn.ifengkou.test.filter.CORSFilter</filter-class>

</filter>

<filter-mapping>

    <filter-name>cros</filter-name>

     <url-pattern>/*</url-pattern>

</filter-mapping>

新增CORSFilter 类

@Component

public class CORSFilter extends OncePerRequestFilter

  @Override

  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)

         throws ServletException, IOException

      response.addHeader("Access-Control-Allow-Origin", "*");

      response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");

      response.addHeader("Access-Control-Allow-Headers", "Content-Type");

      response.addHeader("Access-Control-Max-Age", "1800");//30 min

      filterChain.doFilter(request, response);

     

Access-Control-Allow-Origin只能配置 或者一个域名*
比如配置了192.168.56.130,那么只有192.168.56.130 能拿到数据,否则全部报403异常

response.addHeader("Access-Control-Allow-Origin", "http://192.168.56.130");

二:Nginx 配置支持Ajax跨域

这里是一个nginx启用COSR的参考配置:来源

#

# Wide-open CORS config for nginx

#

location /

   if ($request_method = ‘OPTIONS‘)

     add_header ‘Access-Control-Allow-Origin‘ ‘*‘;

     add_header ‘Access-Control-Allow-Methods‘ ‘GET, POST, OPTIONS‘;

       #

       # Custom headers and headers various browsers *should* be OK with but aren‘t

       #

       add_header ‘Access-Control-Allow-Headers‘ ‘DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type‘;

       #

       # Tell client that this pre-flight info is valid for 20 days

       #

        add_header ‘Access-Control-Max-Age‘ 1728000;

       add_header ‘Content-Type‘ ‘text/plain charset=UTF-8‘; 

       add_header ‘Content-Length‘ 0;

       return 204;

     

   if ($request_method = ‘POST‘)

       add_header ‘Access-Control-Allow-Origin‘ ‘*‘;

       add_header ‘Access-Control-Allow-Methods‘ ‘GET, POST, OPTIONS‘;

       add_header ‘Access-Control-Allow-Headers‘ ‘DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type‘;

   

   if ($request_method = ‘GET‘)

       add_header ‘Access-Control-Allow-Origin‘ ‘*‘;

       add_header ‘Access-Control-Allow-Methods‘ ‘GET, POST, OPTIONS‘;

       add_header ‘Access-Control-Allow-Headers‘ ‘DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type‘;

     

三:支持多域名配置的CORS Filter

因为知道已经有可以用的库可以解决,所以就没重复造轮子了。其实因为懒,看看别人的源码算了。。。

mvnrepository搜索cors-filter,目前也就两个可以用

这两个也都大同小异,因为ebay开源在github上,也有详细的README,那么就以ebay的cors-filter为例

配置

添加依赖包到项目

<dependency>

    <groupId>org.ebaysf.web</groupId>

    <artifactId>cors-filter</artifactId>

    <version>1.0.1</version>

</dependency>

添加配置(具体配置项,还是见项目的README.md吧)

<filter>

      <filter-name>CORS Filter</filter-name>

      <filter-class>org.ebaysf.web.cors.CORSFilter</filter-class>

      <init-param>

         <param-name>cors.allowed.origins</param-name>

         <param-value>http://192.168.56.129,http://192.168.56.130</param-value>

     </init-param>

     <init-param>

          <param-name>cors.allowed.methods</param-name>

         <param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>

     </init-param>

     <init-param>

        <param-name>cors.allowed.headers</param-name>

        <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>

     </init-param>

 </filter>

 <filter-mapping>

     <filter-name>CORS Filter</filter-name>

     <url-pattern>/*</url-pattern>

</filter-mapping>

总结

    cors在开发WebService、RESTful API 时经常会遇到,在以前可能直接通过jsonp解决,jsonp怎么样就不多说了。 总之,CORS技术规范出来这么久了,如果不考虑IE6 IE7的问题,那么还是积极拥抱CORS吧

    上文三种解决方案,通过搜索引擎均能找到,但估计大部分都是用的第一种最简单的无脑的Cors Filter处理,第二种方案是通过nginx配置的,并不适合所有Web应用。第三种,考虑得很周全,而且使用方便,如果不考虑造重复轮子,推荐使用。

本文转载自路径:http://www.cnblogs.com/sloong/p/cors.html

跨域的几种方法(代码片段)

1、jsonp最常见的一种跨域方式,其背后原理就是利用了script标签不受同源策略的限制,在页面中动态插入了script,script标签的src属性就是后端api接口的地址,并且以get的方式将前端回调处理函数名称告诉后端,后端在响应请求时... 查看详情

跨域的几种方法

js中几种实用的跨域方法原理详解(转自:http://www.cnblogs.com/2050/p/3191744.html)这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据... 查看详情

解决geoserver请求跨域的几种思路

1.背景描述    跨域问题是浏览器同源安全制引起的特别常见的问题。不同前端语言针对跨域解决方法有所区别。比如Flex语言做跨域请求时,如果中间件存有跨域文件(crossdomain.xml)则可以轻松实现跨域。  ... 查看详情

vue开发环境和生产环境里面解决跨域的几种方法(代码片段)

  跨域指浏览器不允许当前页面的所在的源去请求另一个源的数据。源指协议,端口,域名。只要这个3个中有一个不同就是跨域。这里列举一个经典的列子:#协议跨域http://a.baidu.com访问https://a.baidu.com;#端口跨域http://a.ba... 查看详情

跨域的几种方法及案例代码

1、通过动态script实现跨域functionloadScript(url,func){ varhead=document.head||document.getElementByTagName(‘head‘)[0]; varscript=document.createElement(‘script‘); script.src=url; script.onload=scri 查看详情

springboot中实现跨域的5种方式(代码片段)

对于CORS的跨域请求,主要有以下几种方式可供选择:1、返回新的CorsFilter(全局跨域)packagecom.cfit.framework.config;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.cors.Cor... 查看详情

解决geoserver请求跨域的几种思路,第二种思路用过

1.背景描述    跨域问题是浏览器同源安全制引起的特别常见的问题。不同前端语言针对跨域解决方法有所区别。比如Flex语言做跨域请求时,如果中间件存有跨域文件(crossdomain.xml)则可以轻松实现跨域。  ... 查看详情

依靠前端解决跨域问题的几种方式

首先我们先了解下跨域的概念:  出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建... 查看详情

解决浏览器跨域的几种方式

  1、什么是跨域问题  在页面中使用js访问其他网站的数据时,就会出现跨域问题,比如在网站中使用ajax请求其他网站的天气、快递或者其他数据接口时,以及hybridapp中请求数据,浏览器会提  示一下错误... 查看详情

解决geoserver请求跨域的几种思路

...:http://www.cnblogs.com/naaoveGIS/1.背景描述    跨域问题是浏览器同源安全制引起的特别常见的问题。不同前端语言针对跨域解决方法有所区别。比如Flex语言做跨域请求时,如果中间件存有跨域文件(crossdomain.xml)则可... 查看详情

springboot(十三)cors方式实现跨域

什么是跨域?浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域。跨域资源访问是经常会遇到的场景,当一个资源从与该资源本身所在的服务器不同的域或端口请求一个资源时,资源便... 查看详情

前端面试题汇总

...发中跨域的几种解决方案9种常见的前端跨域解决方案(详解)跨域资源共享CORS详解CORS跨域中的preflight请求彻底理解cookie,session,token 查看详情

相关前台跨域的解决方式(代码片段)

title:前端跨域处理方式date:2018-07-0800:37:29categories:Web前端tags:跨域cors关于跨域请求解觉方案问题关于浏览器跨域问题,项目中也遇到了,看了项目上一些代码的处理方式,感觉存在不少不大完善的地方,因此对于跨域,想好好梳... 查看详情

cors(代码片段)

CORS:跨域资源共享,是一种跨域访问的W3C标准,它允许浏览器可以跨源服务器进行请求,可以让ajax实现跨域访问。出现跨域问题的原因是浏览器同源策略导致的,协议+域名+端口三者一致被认为是同源。网站出现同源策略问题... 查看详情

跨域cors详解(转)(代码片段)

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-originresourcesharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。本文详细介绍CORS的内部机制。一、简介CORS需要浏览器和服务器同时支... 查看详情

什么是跨域,以及解决方案

跨域的几种常见的解决方式https://blog.csdn.net/weixin_42039396/article/details/80040099前后端分离与跨域的解决方案(CORS的原理)https://blog.csdn.net/cuixiaogang110/article/details/81948173什么是跨域、怎么解决跨域以及如何实现跨域下的登录https://blo... 查看详情

解决cors跨域的filter(代码片段)

importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.core.Ordered;importjavax.servlet.*;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;/***desc:**@aut 查看详情

跨域请求数据有哪几种方式?

 1、什么是跨域?由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。存在跨域的情况:网络协议不同,如http协议访问https协议。端口不同,如80端口访问8080端口。域名... 查看详情