起因

有同学在nginx站点配置中加了一行Access-Control-Allow-Origin *,导致微信中业务数据异常,抓包看http头有两个Access-Control-Allow-Origin字段,一个是站点自己的域名,一个是*。

为了实现跨域资源访问,在代码和nginx配置中都加了Access-Control-Allow-Origin字段,但是浏览器有个原则,如果有两个Access-Control-Allow-Origin字段,那么都失效,哪个都不信。最终导致了微信中打开异常。

也引出了CORS。

定义和原理

什么是CORS跨站资源共享?

跨站源资源共享(CORS)是一份浏览器技术的规范,提供了 Web 服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略[1],是 JSONP 模式的现代版。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好。另一方面,JSONP 可以在不支持 CORS 的老旧浏览器上运作。现代的浏览器都支持 CORS[2]。

简单说,就是为了实现跨站访问资源的遍历,同时保护浏览器使用者的安全,提出的一种规范。如何保护的安全,在下一结做介绍。

在html中的图片、css、js等静态引用,和ajax发起的动态请求,都受同源策略影响。如果有跨域,都可以用CORS来实现(也有其他方法,CORS是标准)。

跨域请求主要用于:

  • 调用XMLHttpRequest或fetchAPI通过跨站点方式访问资源
  • 网络字体,例如Bootstrap(通过CSS使用@font-face 跨域调用字体)
  • 通过canvas标签,绘制图表和视频。

意义

CORS怎么保护安全

客户端

保护用户访问网站的安全。防止用户在A站登录授权后,在访问恶意网站B时,B站在ajax中请求A站,获取A站的信息。

服务端

保护服务器的静态资源、接口数据等,都被自己信任的域名访问,不被其他未授权的网站拉走数据。

实现

客户端

在header中带上Origin字段,标明是跨域请求。如果需要发送带凭证的数据(cookie、Http认证和客户端SSL证明等),将WithCredentials设为true。

xhr.withCredentials = true;

如果请求服务器是非简单请求,浏览器会发出一个OPTION请求,和服务器协商信息。

服务器

服务器处理流程:
1 http头部是否有origin字段
2 没有,当成普通请求处理。
3 有,是否method是OPTIONS(preflight)
4 不是OPTIONS(简单请求),返Allow-Origin、Allow-Credentials等,并返回正常内容。
5 是,返回Allow-Headers、Allow-Methods等,内容为空。

nginx参考配置

     add_header 'Access-Control-Allow-Origin' 'xxxx';
     add_header 'Access-Control-Allow-Credentials' 'true';
     add_header 'Access-Control-Allow-Methods' 'GET, POST, DELETE, PUT, OPTIONS';
     add_header 'Access-Control-Allow-Headers' 'Accept, Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
     if ($request_method = 'OPTIONS') {
       add_header 'Access-Control-Allow-Origin' 'xxxx';
       add_header 'Access-Control-Max-Age' 1728000;
       add_header 'Access-Control-Allow-Credentials' 'true';
       add_header 'Access-Control-Allow-Methods' 'GET, POST, DELETE, PUT, OPTIONS';
       add_header 'Access-Control-Allow-Headers' 'Accept, Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
       add_header 'Content-Type' 'text/plain charset=UTF-8';
       add_header 'Content-Length' 0;
       return 204;
     }

注意

1、在代码或nginx一个地方修改,不要在一个http头中有多个Access-Control-Allow-Origin字段,否则会触发“起因”中的问题。
2、修改配置最好在nginx配置中修改,其次在代码中修改,但是一定不要两侧都改,容易造成两侧混乱不容易维护。
3、业务站点不要为了省事给Access-Control-Allow-Origin设置为*,权限太开会有安全隐患。
4、按规范实现的浏览器,会做拦截。如果没有填写Access-Control字段或填写错误,即使服务端返回了全部数据,浏览器也会拦截不给页面。

参考

CORS——跨域请求那些事儿
跨域资源共享 CORS 详解
浏览器和服务器实现跨域(CORS)判定的原理

CORS(跨站资源共享)介绍的更多相关文章

  1. SpringSecurity环境下配置CORS跨站资源共享规则

    一.CORS简述 要说明CORS(Cross Origin Resourse-Sharing) 跨站资源共享,就必须先说同源策略.长话短说,同源策略就是向服务端发起请求的时候,以下三项必须与当前浏览器 ...

  2. 跨站资源共享CORS原理深度解析

    我相信如果你写过前后端分离的web应用程序,或者写过一些ajax请求调用,你可能会遇到过CORS错误. CORS是什么? 它与安全性有关吗? 为什么要有CORS?它解决了什么目的? CORS是怎样运行 ...

  3. CORS跨域资源共享你该知道的事儿

    "唠嗑之前,一些客套话" CORS跨域资源共享,这个话题大家一定不陌生了,吃久了大转转公众号的深度技术好文,也该吃点儿小米粥溜溜胃里的缝儿了,今天咱们就再好好屡屡CORS跨域资源共 ...

  4. CORS跨域资源共享

    CORS(跨域资源共享)跨域问题及解决 当使用ajax跨域请求时,浏览器报错:XmlHttpRequest error: Origin null is not allowed by Access-Co ...

  5. 在ASP.NET Web API中实现CORS(跨域资源共享)

    默认情况下,是不允许网页从不同的域访问服务器资源的,访问遵循"同源"策略的原则. 会遇到如下的报错: XMLHttpRequest cannot load http://local ...

  6. django上课笔记7-jQuery Ajax 和 原生Ajax-伪造的Ajax-三种Ajax上传文件方法-JSONP和CORS跨域资源共享

    一.jQuery Ajax 和 原生Ajax from django.conf.urls import url from django.contrib import admin from app01 ...

  7. 跨域漏洞丨JSONP和CORS跨域资源共享

    进入正文之前,我们先来解决个小问题,什么是跨域? 跨域:指的是浏览器不能执行其它网站的脚本,它是由浏览器的同源策略造成的,是浏览器的安全限制! 跨域常见的两种方式,分别是JSONP和CORS. 今天i ...

  8. 彻底掌握CORS跨源资源共享

    本文来自于公众号链接: 彻底掌握CORS跨源资源共享 ) 本文接上篇公众号文章:彻底理解浏览器同源策略SOP 一.概述 在云时代,各种SAAS应用层出不穷,各种互联网API接口越来越丰富,H5技术在微 ...

  9. 浅谈跨域问题,CORS跨域资源共享

    1,何为跨域? 在理解跨域问题之前,你先要了解同源策略和URL,简单叙述: 1)同源策略 三同:协议相同,域名相同,端口相同: 目的:保证用户信息安全,防止恶意网站窃取数据.同源策略是必须的,否则co ...

随机推荐

  1. Linux入门(7)——Ubuntu16.04安装wps并解决系统缺失字体问题

    进入WPS官网下载deb包: http://linux.wps.cn/ 安装,打开终端: cd 下载 ~a21_amd64.deb 解决打开WPS时出现的系统缺失字体问题: 下载 https://pa ...

  2. LINUX 笔记-mv命令

    常用参数: -f :force强制的意思,如果目标文件已经存在,不会询问而直接覆盖 -i :若目标文件已经存在,就会询问是否覆盖 -u :若目标文件已经存在,且比目标文件新,才会更新

  3. 在for、foreach循环体中添加数组元素

    在开发工作中遇到这样一种情形,需要在循环体中动态向遍历中的数组添加元素并在当前循环遍历中使用数组的全部元素. 首先使用foreach循环来遍历数组,将代码简化抽象如下: $arr = array(1, ...

  4. MongoDB固定集合(Capped Collections)

    MongoDB 固定集合(Capped Collections)是性能出色且有着固定大小的集合,对于大小固定,我们可以想象其就像一个环形队列,当集合空间用完后,再插入的元素就会覆盖最初始的头部的元素! ...

  5. Vue源码学习02 初始化模块init.js

    接上篇,我们看到了VUE分了很多模块(initMixin()stateMixin()eventsMixin()lifecycleMixin()renderMixin()),通过使用Mixin模式,都是 ...

  6. WCF 内置跟踪日志

    Web.config 配置文件修改: <system.serviceModel> <diagnostics> <messageLogging logEntireMessa ...

  7. Game of Connections

    Game of Connections Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...

  8. html 自定义标签使用实现方法

    通过指定html命名空间的名字来定义自定义标签:默认的一些标签p div等都在html默认的命名空间下.而自定义的标签可以放在自定义的命名空间下,可通过xmlns:命名空间名 来指定,而自定义标签需要 ...

  9. defer与async

    defer:该属性指定的脚本不会修改DOM,因此代码可以安全的延迟执行. 含defer属性的script标签可以放在任何位置,在页面解析到该script标签时,开始下载脚本,但不会执行脚本,直至DOM ...

  10. linux环境手动编译安装Nginx实践过程 附异常解决

    1.下载nginx源码包并解压 可在http://nginx.org/en/download.html下载.tar.gz的源码包,如(nginx-1.4.7.tar.gz) 或者使用云盘下载   ht ...