zoukankan      html  css  js  c++  java
  • 浏览器跨域问题的总结

    http://blog.sina.com.cn/s/blog_62d3ddc00101al1b.html

    目录

    1.document.domain+iframe情形 2

    2.jQuery下通过jsonp实现跨域 3

    3.服务器端的跨域解决方案 4

    4.IE8下的跨域问题 13

    JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。我们在项目开发中遇到了几种跨域情形,现在进行一些总结,也对互联网上凌乱的东西进行一些总结,着重描述上述一些情景,以下列举跨域问题的几种情形

    URL

    说明

    是否允许通信

    http://www.a.com/a.js
    http://www.a.com/b.js

    同一域名下

    允许

    http://www.a.com/lab/a.js
    http://www.a.com/script/b.js

    同一域名下不同文件夹

    允许

    http://www.a.com:8000/a.js
    http://www.a.com/b.js

    同一域名,不同端口

    不允许

    http://www.a.com/a.js
    https://www.a.com/b.js

    同一域名,不同协议

    不允许

    http://www.a.com/a.js
    http://70.32.92.74/b.js

    域名和域名对应ip

    不允许

    http://www.a.com/a.js
    http://script.a.com/b.js

    主域相同,子域不同

    不允许

    http://www.a.com/a.js
    http://a.com/b.js

    同一域名,不同二级域名(同上)

    不允许(cookie这种情况下也不允许访问)

    http://www.cnblogs.com/a.js
    http://www.a.com/b.js

    不同域名

    不允许

    特别注意两点:

    第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,

    第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
    “URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。

    1.document.domain+iframe情形

    对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。具体的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上document.domain = ‘a.com’;然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以“交互”了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开的把script.a.com的domian设为alibaba.com那显然是会报错地!代码如下:

    www.a.com上的a.html

    document.domain = 'a.com';

    var ifr = document.createElement_x('iframe');

    ifr.src = 'http://script.a.com/b.html';

    ifr.style.display = 'none';

    document.body.appendChild(ifr);

    ifr.onload = function(){

        var doc = ifr.contentDocument || ifr.contentWindow.document;

        // 在这里操纵b.html

        alert(doc.getElementsByTagName_r("h1")[0].childNodes[0].nodeValue);

    };

    script.a.com上的b.html

    document.domain = 'a.com';

    这种方式适用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何页面相互通信。

    备注:

    某一页面的domain默认等于window.location.hostname。主域名是不带www的域名,例如a.com,主域名前面带前缀的通常都为二级域名或多级域名,例如www.a.com其实是二级域名。 domain只能设置为主域名,不可以在b.a.com中将domain设置为c.a.com。

    问题:

    1、安全性,当一个站点(b.a.com)被攻击后,另一个站点(c.a.com)会引起安全漏洞。

    2、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。我们工行商城IM联调过程中尝试过这种方式,最终因为影响页面其他iframe的功能而放弃。最终我们调整了融e购的IM前端结构.

    2.jQuery下通过jsonp实现跨域

    JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。JSON系统开发方法是一种典型的面向数据结构的分析和设计方法,以活动为中心,一连串的活动的顺序组合成一个完整的工作进程。

    $.getJSON(url+"?callback=?",    

               function(json){    

           });  

    $.ajax({    

               url: '',  // 跨域URL   

               type: 'GET',    

               dataType: 'jsonp',    

               jsonp: 'jsoncallback', //默认callback   

               data: mydata, //请求数据   

               timeout: 5000, 

               success: function (json) { //客户端jquery预先定义好的callback函数,成功获取跨域服务器上的json数据后,会动态执行这个callback函数    

                   if(json.actionErrors.length!=0){    

                       alert(json.actionErrors);    

                   }    

               },    

               complete: function(XMLHttpRequest, textStatus){    

                     

               }

           });  

    3.服务器端的跨域解决方案

    最新的W3C标准里是这么实现HTTP跨域请求的Cross-Origin Resource Sharing跨域的目标服务器要返回一系列的Headers,通过这些Headers来控制是否同意跨域。

    Access-Control-Allow-Origin 这个 Header在W3C标准里用来检查该跨域请求是否可以被通过。

    从 http://www.a.com/test.html 发起一个跨域请求,请求的地址为: http://www.b.com/test.php 如果 服务器B返回一个如下的header,Access-Control-Allow-Origin: http://www.a.com,那么,这个来自 http://www.a.com/test.html 的跨域请求就会被通过。在这个过程中, request 还会带上这个header,Access-Control-Allow-Origin 的值可以是通配符 *

    如果是 * 的话,就可以接收来自任意source origin的请求。

    IE8 问题(详情见情景4), 则是通过 XDomainRequest 来实现的这个跨域请求比如类似如下代码就可以实现了:

    var request = new XDomainRequest();
    request.open("GET", xdomainurl);
    request.send();

    也要求对方服务器返回这个头才行。

    服务器端代码的操作示例:

    1.我们可以在java代码中加入 response.setHeader("Access-Control-Allow-Origin", "*");

    2.html的,须要 

    3.“CrossOriginFilter”类,用于支持跨域的 JavaScript 请求,如果您的项目中要支持跨域的服务器推送,可以加入该配置。

    package net.icbc.messager.web;

    import java.io.IOException;

    import java.util.ArrayList;

    import java.util.Arrays;

    import java.util.List;

    import javax.servlet.Filter;

    import javax.servlet.FilterChain;

    import javax.servlet.FilterConfig;

    import javax.servlet.ServletException;

    import javax.servlet.ServletRequest;

    import javax.servlet.ServletResponse;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import net.icbc.messager.web.servlet.TokenServlet;

    import org.apache.log4j.Logger;

    public class CrossOriginFilter implements Filter

    {

       

    private static Logger log = Logger.getLogger(TokenServlet.class);

    // Request headers

        private static final String ORIGIN_HEADER = "Origin";

        private static final String ACCESS_CONTROL_REQUEST_METHOD_HEADER = "Access-Control-Request-Method";

        private static final String ACCESS_CONTROL_REQUEST_HEADERS_HEADER = "Access-Control-Request-Headers";

        // Response headers

        private static final String ACCESS_CONTROL_ALLOW_ORIGIN_HEADER = "Access-Control-Allow-Origin";

        private static final String ACCESS_CONTROL_ALLOW_METHODS_HEADER = "Access-Control-Allow-Methods";

        private static final String ACCESS_CONTROL_ALLOW_HEADERS_HEADER = "Access-Control-Allow-Headers";

        private static final String ACCESS_CONTROL_MAX_AGE_HEADER = "Access-Control-Max-Age";

        private static final String ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER = "Access-Control-Allow-Credentials";

        // Implementation constants

        private static final String ALLOWED_ORIGINS_PARAM = "allowedOrigins";

        private static final String ALLOWED_METHODS_PARAM = "allowedMethods";

        private static final String ALLOWED_HEADERS_PARAM = "allowedHeaders";

        private static final String PREFLIGHT_MAX_AGE_PARAM = "preflightMaxAge";

        private static final String ALLOWED_CREDENTIALS_PARAM = "allowCredentials";

        private static final String ANY_ORIGIN = "*";

        private static final List SIMPLE_HTTP_METHODS = Arrays.asList("GET", "POST", "HEAD");

        private boolean anyOriginAllowed = false;

        private List allowedOrigins = new ArrayList();

        private List allowedMethods = new ArrayList();

        private List allowedHeaders = new ArrayList();

        private int preflightMaxAge = 0;

        private boolean allowCredentials = false;

        public void init(FilterConfig config) throws ServletException

        {

            String allowedOriginsConfig = config.getInitParameter(ALLOWED_ORIGINS_PARAM);

            if (allowedOriginsConfig == null) allowedOriginsConfig = "*";

            String[] allowedOrigins = allowedOriginsConfig.split(",");

            for (String allowedOrigin : allowedOrigins)

            {

                allowedOrigin = allowedOrigin.trim();

                if (allowedOrigin.length() > 0)

                {

                    if (ANY_ORIGIN.equals(allowedOrigin))

                    {

                        anyOriginAllowed = true;

                        this.allowedOrigins.clear();

                        break;

                    }

                    else

                    {

                        this.allowedOrigins.add(allowedOrigin);

                    }

                }

            }

            String allowedMethodsConfig = config.getInitParameter(ALLOWED_METHODS_PARAM);

            if (allowedMethodsConfig == null) allowedMethodsConfig = "GET,POST";

            allowedMethods.addAll(Arrays.asList(allowedMethodsConfig.split(",")));

            String allowedHeadersConfig = config.getInitParameter(ALLOWED_HEADERS_PARAM);

            if (allowedHeadersConfig == null) allowedHeadersConfig = "X-Requested-With,Content-Type,Accept,Origin";

            allowedHeaders.addAll(Arrays.asList(allowedHeadersConfig.split(",")));

            String preflightMaxAgeConfig = config.getInitParameter(PREFLIGHT_MAX_AGE_PARAM);

            if (preflightMaxAgeConfig == null) preflightMaxAgeConfig = "1800"; // Default is 30 minutes

            try

            {

                preflightMaxAge = Integer.parseInt(preflightMaxAgeConfig);

            }

            catch (NumberFormatException x)

            {

                log.info("Cross-origin filter, could not parse '{}' parameter as integer: {}"+ PREFLIGHT_MAX_AGE_PARAM+ preflightMaxAgeConfig);

            }

            String allowedCredentialsConfig = config.getInitParameter(ALLOWED_CREDENTIALS_PARAM);

            if (allowedCredentialsConfig == null) allowedCredentialsConfig = "false";

            allowCredentials = Boolean.parseBoolean(allowedCredentialsConfig);

            log.debug("Cross-origin filter configuration: " +

                      ALLOWED_ORIGINS_PARAM + " = " + allowedOriginsConfig + ", " +

                      ALLOWED_METHODS_PARAM + " = " + allowedMethodsConfig + ", " +

                      ALLOWED_HEADERS_PARAM + " = " + allowedHeadersConfig + ", " +

                      PREFLIGHT_MAX_AGE_PARAM + " = " + preflightMaxAgeConfig + ", " +

                      ALLOWED_CREDENTIALS_PARAM + " = " + allowedCredentialsConfig);

        }

        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException

        {

            handle((HttpServletRequest)request, (HttpServletResponse)response, chain);

        }

        private void handle(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException

        {

            String origin = request.getHeader(ORIGIN_HEADER);

            // Is it a cross origin request ?

            if (origin != null && isEnabled(request))

            {

                if (originMatches(origin))

                {

                    if (isSimpleRequest(request))

                    {

                        log.debug("Cross-origin request to {} is a simple cross-origin request"+ request.getRequestURI());

                        handleSimpleResponse(request, response, origin);

                    }

                    else

                    {

                        log.debug("Cross-origin request to {} is a preflight cross-origin request" +request.getRequestURI());

                        handlePreflightResponse(request, response, origin);

                    }

                }

                else

                {

                    log.debug("Cross-origin request to " + request.getRequestURI() + " with origin " + origin + " does not match allowed origins " + allowedOrigins);

                }

            }

            chain.doFilter(request, response);

        }

        protected boolean isEnabled(HttpServletRequest request)

        {

            // WebSocket clients such as Chrome 5 implement a version of the WebSocket

            // protocol that does not accept extra response headers on the upgrade response

            if ("Upgrade".equalsIgnoreCase(request.getHeader("Connection")) &&

                "WebSocket".equalsIgnoreCase(request.getHeader("Upgrade")))

            {

                return false;

            }

            return true;

        }

        private boolean originMatches(String origin)

        {

            if (anyOriginAllowed) return true;

            for (String allowedOrigin : allowedOrigins)

            {

                if (allowedOrigin.equals(origin)) return true;

            }

            return false;

        }

        private boolean isSimpleRequest(HttpServletRequest request)

        {

            String method = request.getMethod();

            if (SIMPLE_HTTP_METHODS.contains(method))

            {

                // TODO: implement better section 6.1

                // Section 6.1 says that for a request to be simple, custom request headers must be simple.

                // Here for simplicity I just check if there is a Access-Control-Request-Method header,

                // which is required for preflight requests

                return request.getHeader(ACCESS_CONTROL_REQUEST_METHOD_HEADER) == null;

            }

            return false;

        }

        private void handleSimpleResponse(HttpServletRequest request, HttpServletResponse response, String origin)

        {

            response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, origin);

            if (allowCredentials) response.setHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");

        }

        private void handlePreflightResponse(HttpServletRequest request, HttpServletResponse response, String origin)

        {

            // Implementation of section 5.2

            // 5.2.3 and 5.2.5

            boolean methodAllowed = isMethodAllowed(request);

            if (!methodAllowed) return;

            // 5.2.4 and 5.2.6

            boolean headersAllowed = areHeadersAllowed(request);

            if (!headersAllowed) return;

            // 5.2.7

            response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, origin);

            if (allowCredentials) response.setHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");

            // 5.2.8

            if (preflightMaxAge > 0) response.setHeader(ACCESS_CONTROL_MAX_AGE_HEADER, String.valueOf(preflightMaxAge));

            // 5.2.9

            response.setHeader(ACCESS_CONTROL_ALLOW_METHODS_HEADER, commify(allowedMethods));

            // 5.2.10

            response.setHeader(ACCESS_CONTROL_ALLOW_HEADERS_HEADER, commify(allowedHeaders));

        }

        private boolean isMethodAllowed(HttpServletRequest request)

        {

            String accessControlRequestMethod = request.getHeader(ACCESS_CONTROL_REQUEST_METHOD_HEADER);

            log.debug("{} is {}"+ ACCESS_CONTROL_REQUEST_METHOD_HEADER+ accessControlRequestMethod);

            boolean result = false;

            if (accessControlRequestMethod != null)

            {

                result = allowedMethods.contains(accessControlRequestMethod);

            }

            log.debug("Method {} is" + (result ? "" : " not") + " among allowed methods {}"+accessControlRequestMethod+allowedMethods);

            return result;

        }

        private boolean areHeadersAllowed(HttpServletRequest request)

        {

            String accessControlRequestHeaders = request.getHeader(ACCESS_CONTROL_REQUEST_HEADERS_HEADER);

            log.debug("{} is {}"+ ACCESS_CONTROL_REQUEST_HEADERS_HEADER+  accessControlRequestHeaders);

            boolean result = true;

            if (accessControlRequestHeaders != null)

            {

                String[] headers = accessControlRequestHeaders.split(",");

                for (String header : headers)

                {

                    boolean headerAllowed = false;

                    for (String allowedHeader : allowedHeaders)

                    {

                        if (header.trim().equalsIgnoreCase(allowedHeader.trim()))

                        {

                            headerAllowed = true;

                            break;

                        }

                    }

                    if (!headerAllowed)

                    {

                        result = false;

                        break;

                    }

                }

            }

            log.debug("Headers [{}] are" + (result ? "" : " not") + " among allowed headers {}"+accessControlRequestHeaders+allowedHeaders);

            return result;

        }

        private String commify(List strings)

        {

            StringBuilder builder = new StringBuilder();

            for (int i = 0; i < strings.size(); ++i)

            {

                if (i > 0) builder.append(",");

                String string = strings.get(i);

                builder.append(string);

            }

            return builder.toString();

        }

        public void destroy()

        {

            anyOriginAllowed = false;

            allowedOrigins.clear();

            allowedMethods.clear();

            allowedHeaders.clear();

            preflightMaxAge = 0;

            allowCredentials = false;

        }

    }

    Fileter配置信息:

             cross-origin

             net.icbc.messager.web.CrossOriginFilter

         

         

             cross-origin

             /*

         

    4.IE8下的跨域问题

    情景4需在情景3的基础上进行,仅仅进行情景3的设置,是在IE8下行不通的.

    通过使用 Internet Explorer 8 中的跨域请求(缩写为“XDR”),开发人员可以创建跨网站数据聚合方案。 这个名为 XDomainRequest 的请求与 XMLHttpRequest 对象类似,但编程模型更加简单,它可以提供一种最简单的方式来向支持 XDR 的第三方站点发出匿名请求,并选择使这些站点的数据可跨域使用。 只需三行代码即可生成基本的跨站点请求。 这将确保针对公共站点(例如,博客或其他社交网络应用程序)的数据聚合简单、安全和快速。

    下面的 JavaScript 代码介绍 XDomainRequest 对象及其事件、属性和方法。 XDomainRequest 参考页提供了比此处更为详细的信息。

    // Creates a new XDR object.

    xdr = new XDomainRequest();  

    // Indicates there is an error and the request cannot be completed. 

    xdr.onerror = alert_error;

                            

    // The request has reached its timeout. 

    xdr.ontimeout = alert_timeout;

                            

    // The object has started returning data.

    xdr.onprogress = alert_progress;

                            

    // The object is complete. 

    xdr.onload = alert_loaded;

    // Sets the timeout interval.

    xdr.timeout = timeout;

    // Gets the content-type header in the request.

    var content_type = xdr.contentType;

    // Gets the body of the response.

    var response = xdr.responseText;

                            

    // Creates a connection with a domain's server. 

    xdr.open("get", url);

    // Transmits a data string to the server. 

    xdr.send();

    // Terminates a pending send.

    xdr.abort();

    附:IE8下的跨域js的兼容设置,实现XDR对象到XHR对象的转换 ieXDRToXHR.js (注此js会对jQuery形成干扰)

    if (window.XDomainRequest) {

        windows.ieXDRToXHR = function(window) {

            "use strict";

            var XHR = window.XMLHttpRequest;

            window.XMLHttpRequest = function() {

                this.onreadystatechange = Object;

                this.xhr = null;

                this.xdr = null;

                this.readyState = 0;

                this.status = '';

                this.statusText = null;

                this.responseText = null;

                this.getResponseHeader = null;

                this.getAllResponseHeaders = null;

                this.setRequestHeader = null;

                this.abort = null;

                this.send = null;

                this.isxdr = false;

                // static binding

                var self = this;

                self.xdrLoadedBinded = function() {

                    self.xdrLoaded();

                };

                self.xdrErrorBinded = function() {

                    self.xdrError();

                };

                self.xdrProgressBinded = function() {

                    self.xdrProgress();

                };

                self.xhrReadyStateChangedBinded = function() {

                    self.xhrReadyStateChanged();

                };

            };

            XMLHttpRequest.prototype.open = function(method, url, asynch, user, pwd) {

                //improve CORS deteciton (chat.example.net exemple.net), remove hardcoded http-bind

                var parser = document.createElement_x('a');

                parser.href = url;

                if (parser.hostname!=document.domain) {

                    if (this.xdr === null){

                        this.xdr = new window.XDomainRequest();

                    }

                    this.isxdr = true;

                    this.setXDRActive();

                    this.xdr.open(method, url);

                } else {

                    if (this.xhr === null){

                        this.xhr = new XHR();

                    }

                    this.isxdr = false;

                    this.setXHRActive();

                    this.xhr.open(method, url, asynch, user, pwd);

                }

            };

            XMLHttpRequest.prototype.xdrGetResponseHeader = function(name) {

                if (name === 'Content-Type' && this.xdr.contentType > ''){

                    return this.xdr.contentType;

                }

                return '';

            };

            

            XMLHttpRequest.prototype.xdrGetAllResponseHeaders = function() {

                return (this.xdr.contentType > '') ? 'Content-Type: ' + this.xdr.contentType : '';

            };

            

            XMLHttpRequest.prototype.xdrSetRequestHeader = function(name, value) {

                //throw new Error('Request headers not supported');

            };

            

            XMLHttpRequest.prototype.xdrLoaded = function() {

                if (this.onreadystatechange !== null) {

                    this.readyState = 4;

                    this.status = 200;

                    this.statusText = 'OK';

                    this.responseText = this.xdr.responseText;

                    if (window.ActiveXObject){

                        var doc = new ActiveXObject('Microsoft.XMLDOM');

                        doc.async='false';

                        doc.loadXML(this.responseText);

                        this.responseXML = doc;

                    }

                    this.onreadystatechange();

                }

            };

            

            XMLHttpRequest.prototype.xdrError = function() {

                if (this.onreadystatechange !== null) {

                    this.readyState = 4;

                    this.status = 0;

                    this.statusText = '';

                    // ???

                    this.responseText = '';

                    this.onreadystatechange();

                }

            };

            

            XMLHttpRequest.prototype.xdrProgress = function() {

                if (this.onreadystatechange !== null && this.status !== 3) {

                    this.readyState = 3;

                    this.status = 3;

                    this.statusText = '';

                    this.onreadystatechange();

                }

            };

            

            XMLHttpRequest.prototype.finalXDRRequest = function() {

                var xdr = this.xdr;

                delete xdr.onload;AZ

                delete xdr.onerror;

                delete xdr.onprogress;

            };

            

            XMLHttpRequest.prototype.sendXDR = function(data) {

                var xdr = this.xdr;

                xdr.onload = this.xdrLoadedBinded;

                xdr.onerror = this.xdr.ontimeout = this.xdrErrorBinded;

                xdr.onprogress = this.xdrProgressBinded;

                this.responseText = null;

                this.xdr.send(data);

            };

            

            XMLHttpRequest.prototype.abortXDR = function() {

                this.finalXDRRequest();

                this.xdr.abort();

            };

            

            XMLHttpRequest.prototype.setXDRActive = function() {

                this.send = this.sendXDR;

                this.abort = this.abortXDR;

                this.getResponseHeader = this.xdrGetResponseHeader;

                this.getAllResponseHeaders = this.xdrGetAllResponseHeaders;

                this.setRequestHeader = this.xdrSetRequestHeader;

            };

            XMLHttpRequest.prototype.xhrGetResponseHeader = function(name) {

                return this.xhr.getResponseHeader(name);

            };

            

            XMLHttpRequest.prototype.xhrGetAllResponseHeaders = function() {

                return this.xhr.getAllResponseHeaders();

            };

            

            XMLHttpRequest.prototype.xhrSetRequestHeader = function(name, value) {

                return this.xhr.setRequestHeader(name, value);

            };

            

            XMLHttpRequest.prototype.xhrReadyStateChanged = function() {

                if (this.onreadystatechange !== null && this.readyState !== this.xhr.readyState) {

                    var xhr = this.xhr;

                    this.readyState = xhr.readyState;

                    if (this.readyState === 4) {

                        this.status = xhr.status;

                        this.statusText = xhr.statusText;

                        this.responseText = xhr.responseText;

                        this.responseXML = xhr.responseXML;

                    }

                    this.onreadystatechange();

                }

            };

            

            XMLHttpRequest.prototype.finalXHRRequest = function() {

                delete this.xhr.onreadystatechange;

            };

            XMLHttpRequest.prototype.abortXHR = function() {

                this.finalXHRRequest();

                this.xhr.abort();

            };

            XMLHttpRequest.prototype.sendXHR = function(data) {

                this.xhr.onreadystatechange = this.xhrReadyStateChangedBinded;

                this.xhr.send(data);

            };

            XMLHttpRequest.prototype.setXHRActive = function() {

                this.send = this.sendXHR;

                this.abort = this.abortXHR;

                this.getResponseHeader = this.xhrGetResponseHeader;

                this.getAllResponseHeaders = this.xhrGetAllResponseHeaders;

                this.setRequestHeader = this.xhrSetRequestHeader;

            };

            windows.ieXDRToXHR = undefined;

        };

        windows.ieXDRToXHR(window);

    }

  • 相关阅读:
    Code Chef December Challenge 2018题解
    UOJ#419. 【集训队作业2018】圆形(格林公式)
    BZOJ2178: 圆的面积并(格林公式)
    LOJ#3052. 「十二省联考 2019」春节十二响(启发式合并)
    LOJ#3048. 「十二省联考 2019」异或粽子(trie树+堆)
    Code Chef MINPOLY(计算几何+dp)
    LOJ#3088. 「GXOI / GZOI2019」旧词(树剖+线段树)
    LOJ#3087. 「GXOI / GZOI2019」旅行者(最短路)
    P5816 [CQOI2010]内部白点
    P5590 赛车游戏
  • 原文地址:https://www.cnblogs.com/8899man/p/5048775.html
Copyright © 2011-2022 走看看