zoukankan      html  css  js  c++  java
  • web跨域问题CORS

    1. 是什么?

    同源策略

    同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSRF等攻击。

    所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

    跨域 (cors)

    cross-origin resource sharing:当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。

    不同域之间相互请求资源,就算作“跨域”。例如:

    http://localhost:8080 -> http://localhost:8088

    2. 为什么?

    浏览器拦截

    跨域并不是没有发出请求,其实请求能发出去,服务端收到请求并正常返回结果,只是结果被浏览器拦截了。

    浏览器为了阻止用户读取到另一个域名下的内容,拦截了ajax响应。

    3. 怎样解决?

    CORS设置头

    只要服务器端设置相应的头允许跨域即可。

    Access-Control-Allow-Origin

    根据Reuqest请求头中的Origin来判断该请求的资源是否可以被共享。

    如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段(该字段的值为服务端设置Access-Control-Allow-Origin的值)便知出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。此时HTTP的返回码为200,所以 这种错误无法通过状态码识别。

    Access-Control-Allow-Credentials

    指定是否允许请求带上cookies,HTTP authentication,client-side SSL certificates等消息。
    如需要带上这些信息,Access-Control-Allow-Credentials:true并需要在XmlHpptRequest中设置xhr.withCredentials=true

    需注意的是,当设置了the credentials flag为true,那么Access-Control-Allow-Origin就不能使用"*"

    Access-Control-Max-Age

    可选字段,指定了一个预请求将缓存多久,在缓存失效前将不会再发送预请求。

    Access-Control-Allow-Methods

    作为预请求Response的一部分,指定了真实请求可以使用的请求方式。

    Access-Control-Allow-Headers

    作为预请求Response的一部分,指定了真实请求可以使用的请求头名称(header field names)。

    golang实现

    CORS需要浏览器和服务器同时支持。整个CORS通信过程,浏览器是自动完成,而服务器需要手动配置。

    golang设置HTTP头部相当简单,标准包有现成的方法可以使用。

    //https://gitee.com/yuxio/epcforedge.git  
        "github.com/gorilla/handlers"
        "github.com/gorilla/mux"
        "golang.org/x/net/http2"
    
        headersOK := handlers.AllowedHeaders([]string{"X-Requested-With",
            "Content-Type", "Authorization"})
        originsOK := handlers.AllowedOrigins(
            []string{AfCtx.cfg.SrvCfg.UIEndpoint})
        methodsOK := handlers.AllowedMethods([]string{"GET", "HEAD",
            "POST", "PUT", "PATCH", "OPTIONS", "DELETE"})
    
        AfRouter = NewAFRouter(AfCtx)
    
        serverCNCA := &http.Server{
            Addr:         AfCtx.cfg.SrvCfg.CNCAEndpoint,
            Handler:      handlers.CORS(headersOK, originsOK, methodsOK)(AfRouter),
            ReadTimeout:  5 * time.Second,
            WriteTimeout: 10 * time.Second,
        }

    示例

    ajax.html

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <script>
            function loadXMLDoc() {
                var xmlhttp;
                if (window.XMLHttpRequest) {
                    xmlhttp = new XMLHttpRequest();
                }
                else {
                    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
                }
                xmlhttp.onreadystatechange = function () {
                    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                        document.getElementById("myDiv").innerHTML = xmlhttp.responseText;
                    }
                }
                xmlhttp.open("GET", "http://127.0.0.1:9000", true);
                xmlhttp.send();
            }
        </script>
        <title>Document</title>
    </head>
    <body>
        <h2>cross origin</h2>
        <button type="button" onclick="loadXMLDoc()">请求数据</button>
        <div id="myDiv"></div>
    </body>
    </html>

    8000port.go

    package main
    
    import (
        "net/http"
        "html/template"
    )
    
    func main(){
        http.HandleFunc("/", Entrance)
        http.ListenAndServe(":8000", nil)
    }
    
    func Entrance(w http.ResponseWriter, r *http.Request){
        t, _ := template.ParseFiles("ajax.html")
        t.Execute(w, nil)
    }

    9000port.go

    package main
    
    import (
        "net/http"
        "fmt"
    )
    
    func main(){
        http.HandleFunc("/", TestCrossOrigin)
        http.ListenAndServe(":9000", nil)
    }
    
    func TestCrossOrigin(w http.ResponseWriter, r *http.Request){
        w.Header().Set("Access-Control-Allow-Origin", "*")
        w.Header().Add("Access-Control-Allow-Headers", "Content-Type")
        w.Header().Set("Content-Type", "text/plain")
        fmt.Fprintln(w, "hello cros!")
    }

    如果注释掉Access-Control-Allow-Origin,不能跨域访问,报如下错误(console):

    Access to XMLHttpRequest at 'http://127.0.0.1:9000/' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

    response Headers:

    参考:

    1. 跨域问题及解决方法 nginx部署 sinksmell  https://github.com/sinksmell/lanblog.git 

    2. golang跨域访问

    3. Web开发之跨域与跨域资源共享  jsonp cros

    4. 前端常见跨域解决方案(全)  jsonp cors nginx nodejs websocket

    5. ajax 廖雪峰 

    6. 跨域资源共享 CORS 详解 阮一峰

  • 相关阅读:
    现代软件工程 第一章 概论 第3题——韩婧
    现代软件工程 第一章 概论 第2题——韩婧
    小组成员邓琨、白文俊、张星星、韩婧
    UVa 10892 LCM的个数 (GCD和LCM 质因数分解)
    UVa 10780 幂和阶乘 求n!中某个因子的个数
    UVa 11859 除法游戏(Nim游戏,质因子)
    Codeforces 703C Chris and Road 二分、思考
    Codeforces 703D Mishka and Interesting sum 树状数组
    hdu 5795 A Simple Nim SG函数(多校)
    hdu 5793 A Boring Question 推公式(多校)
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/12638906.html
Copyright © 2011-2022 走看看