簡體   English   中英

瀏覽器中的“跨源請求被阻止:同源策略”錯誤

[英]“Cross-Origin Request Blocked: The Same Origin Policy” Error in browser

當我嘗試將 json 文件發布到我的服務器時出現此錯誤。

在我的服務器端,代碼是:

    @POST
    @Path("updatedata")
    @Produces("text/plain")
    @Consumes("application/json")
    public Response UpdateData(String info) {
        Gson gson = new Gson();
        List<Data> list = gson.fromJson(info, new TypeToken<List<Data>>() {
        }.getType());

        int is_success = 0;
        try {
            is_success += trainingdata.updateData(list);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        String returnjson = "{\"raw\":\"" + list.size() + "\",\"success\":\"" + is_success + "\"}";
        return Response.ok().entity(returnjson).header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "POST").build();
    }

我可以通過 RESTClient - Chrome 插件成功更新我的數據。

但是當我構建前端並嘗試通過 jaascript 調用 API 時,Firefox 顯示:跨域請求被阻止:同源策略...... Chrome 顯示:XMLHttpRequest 無法加載......沒有'Access-Control-Allow-Origin ' 請求的資源上存在標頭。 Origin '...' 因此不允許訪問

我寫了這樣的javascript:

var json = JSON.stringify(array);

var xhr = new XMLHttpRequest();
xhr.open("POST", "http://myurl:4080/updatedata", true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(json);

xhr.onload = function (e) {
    if (xhr.readyState === 4) {
        if (xhr.status === 200) {
            alert('hello');
        }
    }
};
xhr.onerror = function (e) {
    console.error(xhr.statusText);
};

我的javascript代碼有問題嗎?

我將后端代碼和前端代碼部署在同一台機器上。

GET 函數成功運行。

@GET
@Produces("application/json")
@Path("/{cat_id}")
public Response getAllDataById(@PathParam("cat_id") String cat_id) {
    ReviewedFormat result = null;
    try {
        result = trainingdata.getAllDataById(cat_id);
        Gson gson = new Gson();
        Type dataListType = new TypeToken<ReviewedFormat>() {
        }.getType();
        String jsonString = gson.toJson(result, dataListType);
        return Response.ok().entity(jsonString).header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "GET").build();

    } catch (SQLException e) {
        logger.warn(e.getMessage());
    }
    return null;
}

前端:

var xhr = new XMLHttpRequest();
xhr.open("GET", "http://URL:4080/mywebservice/v1/trainingdata/" + cat_id, true);

xhr.onload = function (e) {
    if (xhr.readyState === 4) {
        if (xhr.status === 200) {
            //console.log(xhr.responseText);
            var jsoninfo = xhr.responseText;
            var obj = JSON.parse(jsoninfo);
        }
     }
}

CORS 通過不依賴其他人的資源(可能會死)來防止跨站點攻擊發生問題並強制進行智能開發。 它是大多數服務器和瀏覽器的默認安全功能。

在 Apache 中,您可以通過添加標頭來禁用 CORS,IIS 和 AppEngine 的工作方式類似。

由於您是在本地開發,因此您最好的選擇是 XAMPP/WAMPP 加上適當的標頭 - 或者干脆切換到 FireFox。

FireFox 不考慮 CORS 下的本地文件,而大多數瀏覽器會考慮。

阿帕奇修復

添加標題->

Header set Access-Control-Allow-Origin "*"

重置服務器 ->

apachectl -t
  • 須藤服務 apache2 重新加載

IIS修復:

修改根目錄下的web.config(類似HTAccess)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <system.webServer>
   <httpProtocol>
     <customHeaders>
       <add name="Access-Control-Allow-Origin" value="*" />
     </customHeaders>
   </httpProtocol>
 </system.webServer>
</configuration>

應用引擎

Python 的頭方法:self.response.headers.add_header()

class CORSEnabledHandler(webapp.RequestHandler):
  def get(self):
    self.response.headers.add_header("Access-Control-Allow-Origin", "*")
    self.response.headers['Content-Type'] = 'text/csv'
    self.response.out.write(self.dump_csv())

對於 Java :resp.addHeader()

public void doGet(HttpServletRequest req, HttpServletResponse resp) {
  resp.addHeader("Access-Control-Allow-Origin", "*");
  resp.addHeader("Content-Type", "text/csv");
  resp.getWriter().append(csvString);
}

對於 Go :w.Header().Add()

func doGet(w http.ResponseWriter, r *http.Request) {
  w.Header().Add("Access-Control-Allow-Origin", "*")
  w.Header().Add("Content-Type", "text/csv")
  fmt.Fprintf(w, csvData)
}

如果您對 GET 請求感興趣,可以通過 JSONP 繞過 CORS 問題: http : //en.wikipedia.org/wiki/JSONP

這是由在 javascript 中進行跨域請求引起的問題。 出於安全原因,瀏覽器會阻止這種情況。

在 javascript 中,默認情況下您不能向不同的域(包括不同的端口)發出請求。

如果您需要向另一個域發送請求,您可以選擇啟用 CORS 或使用反向代理。

聽起來您可以控制要發布到的遠程資源。 如果是這種情況,您的遠程資源需要具有以下標頭:

Access-Control-Allow-Origin: http://yourrequestingurl.com

更多信息在這里(看起來有人已經問過像你這樣的問題): 跨源請求被阻止:同源策略不允許在以下位置讀取遠程資源

感謝@TGH 的提示,我終於通過添加網絡代理解決了問題。

請參閱使用 Web 代理,我創建了一個 proxy.php 文件,該文件接收 Javascript 的 xmlHttpRequest,獲取 postdata 並調用 Web 服務 API。

<?php

$method = isset($_POST['method']) ? $_POST['method'] : 'POST';
$postData = file_get_contents('php://input');
$url = $envArray['url'] . ':' . $envArray['port'] . '/mywebservice/v1/trainingdata/updatedata';

echo curl($url, $postData, $method);
}

function curl($url = '', $params = '', $method = 'POST'){
    if (empty($url)) {
        error_log('Curl URL is empty.');
        return;
    }
    $envArray = Settings::getEnvAry();

    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);                                                                     
    curl_setopt($ch, CURLOPT_POSTFIELDS, html_entity_decode($params, ENT_QUOTES));
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(                                                                          
            'Content-Type: application/json',                                                                                
            'Content-Length: ' . strlen($params)
        )                                                                       
    );
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);                                                                      

    $response = curl_exec($ch);
    $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $rs = array('status' => $http_status, 'response' => $response);

    return json_encode($rs);
}
?>

在前端,我調用了 proxy.php

 var xhr = new XMLHttpRequest();
    xhr.open("POST", "proxy.php", true);
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.send(json);

我認為這更適合將項目部署到遠程框,而不是修改 Apache 配置。

您可以在 Nginx 配置中添加標頭,並在其他 Web 服務器中類似

例子

add_header Access-Control-Allow-Origin *;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM