HTTP 跨域名请求(CORS)

同源策略


出于安全考虑,浏览器会限制脚本中发起的跨域请求。比如,使用 XMLHttpRequest 对象和Fetch发起 HTTP 请求就必须遵守同源策略。

具体而言,Web 应用程序通过 XMLHttpRequest 对象或Fetch能且只能向同域名的资源发起 HTTP 请求,而不能向任何其它域名发起请求。

 

CORS(Cross-Origin Resource Sharing)


隶属于 W3C 的 Web 应用工作组( Web Applications Working Group )推荐了一种新的机制,即跨源资源共享(Cross-Origin Resource Sharing (CORS))。这种机制让Web应用服务器能支持跨站访问控制,从而使得安全地进行跨站数据传输成为可能。

1.简单请求
  • 只使用 GET,HEAD 或者 POST请求方法。如果使用 POST 向服务器端传送数据,则数据类型(Content-Type)只能是 application/x-www-form-urlencoded, multipart/form-data 或 text/plain中的一种。
  • 不会使用自定义请求头(类似于 X-Modified 这种)。

Note: 这些跨站请求与以往浏览器发出的跨站请求并无异同。并且,如果服务器不给出适当的响应头,则不会有任何数据返回给请求方。

如果服务器端仅允许来自 http://foo.example 的跨站请求,它可以返回: Access-Control-Allow-Origin: http://foo.example 

2.预请求(Preflighted requests)

“预请求”要求必须先发送一个 OPTIONS 请求给目的站点*,来查明这个跨站请求对于目的站点是不是安全可接受的。这样做,是因为跨站请求可能会对目的站点的数据造成破坏。 当请求具备以下条件,就会被当成预请求处理:

  • 请求以 GET, HEAD 或者 POST 以外的方法发起请求。或者,使用 POST,但请求数据为 application/x-www-form-urlencoded, multipart/form-data 或者 text/plain 以外的数据类型。比如说,用 POST 发送数据类型为 application/xml 或者 text/xml 的 XML 数据的请求。
  • 使用自定义请求头(比如添加诸如 X-PINGOTHER)
3.附带凭证信息的请求(support cookies)

如果request请求要支持HTTP Cookies和验证信息,那么,XMLHttpRequest需要将withCredentials属性设置为true而response需要返回Access-Control-Allow-Credentials: true

前端代码:

// JS
var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/credentialed-content/';

function callOtherDomain(){
  if(invocation) {
    invocation.open('GET', url, true);
    invocation.withCredentials = true;   // 设置
    invocation.onreadystatechange = handler;
    invocation.send(); 
  }

// JQuery
 $.ajax({
   ...
   url: a_cross_domain_url,
   xhrFields: {
      withCredentials: true
   }
 });

4.HTTP 响应头
(1)Access-Control-Allow-Origin
Access-Control-Allow-Origin: <origin> | *

origin参数指定一个允许向该服务器提交请求的URI。对于一个不带有credentials的请求,可以指定为'*',表示允许来自所有域的请求。

还可以指定具体的域,比如:

Access-Control-Allow-Origin: http://mozilla.com

如果服务器端指定了域名,而不是'*',那么响应头的Vary值里必须包含Origin.它告诉客户端: 响应是根据请求头里的Origin的值来返回不同的内容的。

 

 

什么是跨域请求


概述

​在 HTML 中,<a>, <form>, <img>, <script>, <iframe>, <link> 等标签以及 Ajax 都可以指向一个资源地址,而所谓的跨域请求就是指:当前发起请求的域与该请求指向的资源所在的域不一样。这里的域指的是这样的一个概念:我们认为若协议 + 域名 + 端口号均相同,那么就是同域。

HTML中a/form/img/css/script/iframe/ajax都可以指向资源
发起请求的资源所在域不同于该请求所指向资源所在的域的HTTP请求就叫做跨域HTTP请求 

​举个例子:假如一个域名为aaa.cn的网站,它发起一个资源路径为aaa.cn/books/getBookInfo的 Ajax 请求,那么这个请求是同域的,因为资源路径的协议、域名以及端口号与当前域一致(例子中协议名默认为http,端口号默认为80)。但是,如果发起一个资源路径为bbb.com/pay/purchase的 Ajax 请求,那么这个请求就是跨域请求,因为域不一致,与此同时由于安全问题,这种请求会受到同源策略限制。

跨源 HTTP 请求的一个例子:运行在 https://domain-a.com 的 JavaScript 代码使用 XMLHttpRequest 来发起一个到 https://domain-b.com/data.json 的请求。

出于安全性,浏览器限制脚本内发起的跨源 HTTP 请求。例如,XMLHttpRequest 和 Fetch API 遵循同源策略。这意味着使用这些 API 的 Web 应用程序只能从加载应用程序的同一个域请求 HTTP 资源,除非响应报文包含了正确 CORS 响应头。

何为不同域

协议+域名+端口号都相同才是同域

CORS 机制允许 Web 应用服务器进行跨源访问控制,从而使跨源数据传输得以安全进行。现代浏览器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch)使用 CORS,以降低跨源 HTTP 请求所带来的风险。 

跨域请求的安全问题

​通常,浏览器会对上面提到的跨域请求作出限制。浏览器之所以要对跨域请求作出限制,是出于安全方面的考虑,因为跨域请求有可能被不法分子利用来发动 CSRF攻击。

如果对跨域请求不做限制,会有安全隐患
例1:一个恶意网站的页面通过iframe嵌入了支付宝的登录页面(两者不同域),如果没有任何限制,恶意网页上的javascript脚本就可以在用户登录银行的时候获取用户名和密码

例2:跨域请求别人的AJAX登录接口,也可以获取到用户名密码 

CSRF攻击:

​ CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。CSRF攻击者在用户已经登录目标网站之后,诱使用户访问一个攻击页面,利用目标网站对用户的信任,以用户身份在攻击页面对目标网站发起伪造用户操作的请求,达到攻击目的。

​ CSRF 攻击的原理大致描述如下:有两个网站,其中A网站是真实受信任的网站,而B网站是危险网站。在用户登陆了受信任的A网站是,本地会存储A网站相关的Cookie,并且浏览器也维护这一个Session会话。这时,如果用户在没有登出A网站的情况下访问危险网站B,那么危险网站B就可以模拟发出一个对A网站的请求(跨域请求)对A网站进行操作,而在A网站的角度来看是并不知道请求是由B网站发出来的(Session和Cookie均为A网站的),这时便成功发动一次CSRF 攻击。

​ 因而 CSRF 攻击可以简单理解为:攻击者盗用了你的身份,以你的名义发送而已请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。

​ 因此,大多数浏览器都会跨域请求作出限制,这是从浏览器层面上的对 CSRF 攻击的一种防御,但是需要注意的是在复杂的网络环境中借助浏览器来防御 CSRF 攻击并不足够,还需要从服务端或者客户端方面入手防御。详细可以参考这篇文章浅谈CSRF攻击方式


 

如何限制跨域请求


  1. 不允许跨域请求
    NO
  2. 服务端
    可以根据相关的HEADER判断来源,限制访问
    但是HEADER可以伪造
  3. 浏览器
    发起跨域请求时,进行限制
    同源策略 
同源策略

是浏览器的一种约定和安全功能,对跨域请求进行控制
1:限制来自不同源的document或脚本,对当前document读取或设置某些属性
2:禁止ajax直接发起跨域HTTP请求(其实可以发送请求,结果被浏览器拦截,不展示)
3:允许img/css/script(拥有src的标签都有跨域的能力。加载下来就属于当前域了)
4:允许跨域的连接、跳转、表单提交(带来了跨站请求伪造CSRF问题) 

同源策略的作用

解决了例1里面的问题:
恶意网站的JS无法读取iframe里面的内容
因为iframe加载之后属于单独的一个window当然也是一个单独的document

解决了例2里面的问题:
发起的AJAX请求结果如何被浏览器屏蔽了,虽然实际请求已经发送到服务端,但是不知道结果(所以服务端也要有相应的策略) 

示例:

server {
            #listen       443 ssl;
            listen       16443 ;
            server_name zjapp6-test.hrfax.cn;

          if ($request_method ~* PUT|DELETE) {
                return 403;
            }
           
            location ~*\.(jsp|php) {
                deny all;
                return 404;
            }

            location / {
        if ($request_method = 'OPTIONS') {
            # 处理预检请求
            #add_header 'Access-Control-Allow-Origin' 'https://bocsign-h5-test12.hrfax.cn, http://192.168.12.112:83';
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Type' 'text/plain charset=UTF-8';
            add_header 'Access-Control-Allow-Headers' '*';
            add_header 'Content-Length' 0;
            return 204;
        }
                #ua_log4j
                if ($http_user_agent ~ "jndi|ldap|\$"){
                    return 403;
                }

                include proxy.conf;
                proxy_pass http://192.168.12.112:9087;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
           }

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值