zoukankan      html  css  js  c++  java
  • cors

    起因

    有同学在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)判定的原理

  • 相关阅读:
    我是如何学习写一个操作系统(七):进程的同步与信号量
    我是如何学习写一个操作系统(六):进程的调度
    我是如何学习写一个操作系统(五):故事的高潮之进程和线程1
    我是如何学习写一个操作系统(四):操作系统之系统调用
    我是如何学习写一个操作系统(三):操作系统的启动之保护模式
    我是如何学习写一个操作系统(二):操作系统的启动之Bootloader
    我是如何学习写一个操作系统(一):开篇
    Android计量单位px,in,mm,pt,dp,dip,sp和获取屏幕尺寸与密度
    Azure自定义角色实现RBAC
    Linux两块4TB的数据磁盘创建8TB的Raid0
  • 原文地址:https://www.cnblogs.com/yelongsan/p/7998765.html
Copyright © 2011-2022 走看看