跨域请求被阻止

Posted

技术标签:

【中文标题】跨域请求被阻止【英文标题】:Cross-Origin Request Blocked 【发布时间】:2014-04-17 06:44:35 【问题描述】:

所以我有了这个 Go http 处理程序,它将一些 POST 内容存储到数据存储中并检索一些其他信息作为响应。在我使用的后端:

func handleMessageQueue(w http.ResponseWriter, r *http.Request) 
    w.Header().Set("Access-Control-Allow-Origin", "*")
    if r.Method == "POST" 

        c := appengine.NewContext(r)

        body, _ := ioutil.ReadAll(r.Body)

        auth := string(body[:])
        r.Body.Close()
        q := datastore.NewQuery("Message").Order("-Date")

        var msg []Message
        key, err := q.GetAll(c, &msg)

        if err != nil 
            c.Errorf("fetching msg: %v", err)
            return
        

        w.Header().Set("Content-Type", "application/json")
        jsonMsg, err := json.Marshal(msg)
        msgstr := string(jsonMsg)
        fmt.Fprint(w, msgstr)
        return
    

在我使用的 Firefox OS 应用中:

var message = "content";

request = new XMLHttpRequest();
request.open('POST', 'http://localhost:8080/msgs', true);

request.onload = function () 
    if (request.status >= 200 && request.status < 400) 
        // Success!
        data = JSON.parse(request.responseText);
        console.log(data);
     else 
        // We reached our target server, but it returned an error
        console.log("server error");
    
;

request.onerror = function () 
    // There was a connection error of some sort
    console.log("connection error");
;

request.send(message);

传入的部分都可以正常工作。但是,我的回复被阻止了。给我以下信息:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/msgs. This can be fixed by moving the resource to the same domain or enabling CORS.

我尝试了很多其他方法,但我无法从服务器获得响应。但是,当我将 Go POST 方法更改为 GET 并通过浏览器访问页面时,我得到了我非常想要的数据。我真的无法确定哪一方出了问题以及原因:可能是 Go 不应该阻止这些类型的请求,但也可能是我的 javascript 是非法的。

【问题讨论】:

在我看来(我没有写这个作为答案,因为我不确定)你没有在请求中设置内容类型。来自 Mozilla 的 TFM 主题:If POST is used to send data to the server, the Content-Type of the data sent to the server with the HTTP POST request is one of application/x-www-form-urlencoded, multipart/form-data, or text/plain 【参考方案1】:

您需要其他标头,而不仅仅是 access-control-allow-origin。 如果您的请求具有“Access-Control-Allow-Origin”标头,则必须将其复制到响应标头中,如果没有,则必须检查“Origin”标头并将其复制到响应中。如果您的请求没有 Access-Control-Allow-Origin 而不是 Origin 标头,则必须返回“*”。

你可以在这里阅读完整的解释:http://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server

这是我用来编写跨域标头的函数:

func writeCrossDomainHeaders(w http.ResponseWriter, req *http.Request) 
    // Cross domain headers
    if acrh, ok := req.Header["Access-Control-Request-Headers"]; ok 
        w.Header().Set("Access-Control-Allow-Headers", acrh[0])
    
    w.Header().Set("Access-Control-Allow-Credentials", "True")
    if acao, ok := req.Header["Access-Control-Allow-Origin"]; ok 
        w.Header().Set("Access-Control-Allow-Origin", acao[0])
     else 
        if _, oko := req.Header["Origin"]; oko 
            w.Header().Set("Access-Control-Allow-Origin", req.Header["Origin"][0])
         else 
            w.Header().Set("Access-Control-Allow-Origin", "*")
        
    
    w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
    w.Header().Set("Connection", "Close")


【讨论】:

我非常想确认您的回答;我似乎无法让它工作。有什么方法可以查看我的 Firefox OS javascript 发送的标头吗?如果我 console.log(request) 我得到:[object DeadObject]。 Golang 端打印以下 w.Header():map[Access-Control-Allow-Credentials:[True] Access-Control-Allow-Origin:[app://d8c37181-3d41-5c40-8a1e-3abfa8cb3955] Access-控制允许方法:[GET,POST]] 我使用萤火虫。它使您可以查看整个请求和响应标头和正文。现在,为什么起源说:app://? 另一件事。您是否在后端回答 OPTIONS 方法?所有跨域请求首先使用 OPTION 方法调用后端,如果该方法使用我在之前的答案中发送的标头进行响应,则发出真正的请求。例如:如果您执行跨域 POST,您的浏览器会向后端发出 OPTIONS 请求,如果答案正确(后端回答正确的 cors 标头),则将执行真正的 POST。 我正在使用 Gorilla/Mux,这就是我处理 OPTIONS 请求的方式: r := mux.NewRouter() r.StrictSlash(true) r.PathPrefix("/").Methods( "OPTIONS").HandlerFunc(writeCrossDomainHeaders) r.Handle("/widget", context.Handler(blah_blah_blah)).Methods("GET") 嗨,卡尔,啊,萤火虫;我应该知道的。来源说 app:// 因为它是我正在运行的 Firefox OS 应用程序。正如@msaad 所说,这个特定的“细节”似乎导致了我的问题。我在搜索 Golang 答案时遇到过几次 Gorilla,但那时我不明白为什么要使用它。但我想我应该再看看;您处理 OPTIONS 请求的方式似乎更方便【参考方案2】:

@Egidius,在创建 XMLHttpRequest 时,你应该使用

var xhr = new XMLHttpRequest(mozSystem: true);

什么是 mozSystem?

mozSystem 布尔值:将此标志设置为 true 允许进行跨站点连接,而无需服务器选择使用 CORS。需要设置 mozAnon: true,即不能与发送 cookie 或其他用户凭据结合使用。这仅适用于特权(已审核)应用程序;它不适用于 Firefox 中加载的任意网页。

清单更改

在您的清单中,不要忘记在您的权限中包含这一行:

"permissions": 
       "systemXHR" : ,

【讨论】:

典型;我应该更好的 rtfm。我之前尝试过 mozSystem xhr arg,但我跳过了清单部分,因为它不是有效的 JSON。现在我刚刚添加了一些废话,我的错误消失了。即使我仍然没有得到回应,我认为这已解决了它,但我的一些更改必须是为了修复现在搞砸这部分的 CORS 错误。非常感谢! 欢迎您,Egidius。 Cors 有时可能是无稽之谈,但最好默认为 false,因为许多开发人员不了解允许这样做的风险。我很高兴能帮上忙。 感谢您提供此信息,但您有任何消息来源吗?附加信息?它不适合我。 . . @RClaven,当然。这个developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest 可能会对您有所帮助。此外,请确保您没有遇到 CORS 问题而不是权限问题。【参考方案3】:

您必须将此代码放在 application.rb 中

config.action_dispatch.default_headers = 
        'Access-Control-Allow-Origin' => '*',
        'Access-Control-Request-Method' => %wGET POST OPTIONS.join(",")

【讨论】:

以上是关于跨域请求被阻止的主要内容,如果未能解决你的问题,请参考以下文章

socket.io 跨域请求被阻止

跨域请求被阻止原因:CORS 预检通道未成功

jQuery ajax 请求因为跨域而被阻止

AJAX 请求跨域请求被阻止错误

跨域请求被阻止

AngularJS和跨域请求被阻止[关闭]