搜尋

首頁  >  問答  >  主體

CORS:PHP:對預檢請求的回應未通過。我允許原產地

<p>所以我知道那裡有很多 CORS 帖子,我只是添加它們,但我找不到任何可以幫助我的答案。所以我正在建立一個依賴我的 php api 的 Angular 4 應用程式。在本地工作沒問題,當我將其與位於<code>app.example.com</code> 的應用程式和位於<code>api.example.com</code> 的api 一起扔到網域上時,我無法通過我的登錄,因為我得到以下錯誤:</p> <blockquote> <p>XMLHttpRequest 無法載入 http://api.example.com/Account/Login。 對預檢請求的回應未通過存取控制檢查:否 請求中存在「Access-Control-Allow-Origin」標頭 資源。因此不允許來源“http://app.example.com” 訪問。</p> </區塊引用> <p>我的php程式碼如下圖:</p>
$http_origin = $_SERVER['HTTP_ORIGIN'];

$allowed_domains = 陣列(
    'http://example.com',
    'https://example.com',
    'http://app.example.com',
    'https://app.example.com',
    'http://www.example.com',
    'https://www.example.com'
);

if (in_array(strtolower($http_origin), $allowed_domains))
{
    // header("Access-Control-Allow-Origin: *");
    標頭(「存取控制允許來源:$ http_origin」);
    header('存取控制允許憑證:true');
    header('存取控制最大年齡:86400');
}

// 在 OPTIONS 請求期間接收存取控制標頭
if ($_SERVER['REQUEST_METHOD'] == '選項') {
        header("存取控制允許方法:GET、POST、OPTIONS");
        header("存取控制允許標頭:授權、內容類型、接受、來源");
    退出(0);
}</pre>

<p>我的 Angular 貼文如下所示:</p>

<pre class="brush:php;toolbar:false;">公共登入(登入:登入):Observable<LoginResponse> {
    令 headers = new headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    headers.append('授權', '基本' btoa(login.使用者名稱 ':' 登入.密碼));
    回傳 this.http.post(this.apiBaseUrl '/Account/Login', "grant_type=client_credentials", { headers: headers })
        .map(響應=> {
            // 程式碼
        });
}</pre>

<p>如果我透過郵差運行請求(這不會影響 CORS),我會得到:</p>

{ "error": "invalid_client", "error_description": "在標頭或正文中找不到客戶端憑證" }
; <p>我嘗試將 origin 設定為“<code>*</code>”只是為了測試並查看這是否是問題的核心,但它仍然以同樣的方式失敗。</p> <p><strong><em>編</em></strong> 只需根據以下資訊進行更新。更改標頭中的大小寫入沒有任何效果,並且從if語句中取出程式碼也沒有任何效果。</p> <p>我透過告訴我的即時應用程式前往本地 api 來調試 php,並且 php 正在按預期工作。它設定標頭將每個 if 語句中的寫入放入其中。</p> <p><strong><em>編鏡頭2</em></strong> 我確實需要一些幫助,如果有人有任何想法,我將非常感激。</p> <p><strong><em>編輯鏡頭 3</em></strong> 如果我在 .htaccess 而不是 php 中設定所有標頭內容,它就會讓我通過。但是,現在我陷入了上面列出的錯誤,這是我在使用郵遞員時總是遇到的錯誤,但現在是在使用實際網站時遇到的錯誤。 </p> <p><code>{"error":"invalid_client","error_description":"在標頭或正文中找不到客戶端憑證"}</code></p> <p>我的回應標頭是這樣的</p> <pre class="brush:php;toolbar:false;">Access-Control-Allow-Credentials:true Access-Control-Allow-Headers:authorization, content-type, accept, origin Access-Control-Allow-Methods:GET, POST, OPTIONS Access-Control-Allow-Origin:*</pre> <p>一旦它正常工作,我會將其從 * 更改為僅我的網域。但現在我將其保留為 *。 </p> <p><strong>根據要求我的標頭。 </strong></p>
P粉642920522P粉642920522462 天前692

全部回覆(2)我來回復

  • P粉502608799

    P粉5026087992023-08-25 17:38:47

    在我的類似案例中,Angular 前端和 Php 後端幫助了下面的程式碼。首先我發送一個標頭:

    header("Access-Control-Allow-Origin: http://localhost:4200");   
    header("Content-Type: application/json; charset=UTF-8");    
    header("Access-Control-Allow-Methods: POST, DELETE, OPTIONS");    
    header("Access-Control-Max-Age: 3600");    
    header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");

    在他們之後,我可以忽略選項請求:

    if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {    
       return 0;    
    }

    這個方法幫助我處理 Angular 中的「post」和「delete」嵌入請求方法。

    回覆
    0
  • P粉316890884

    P粉3168908842023-08-25 16:25:07

    好吧,我最近遇到了類似的問題,我只在後端解決了所有問題,沒有 .htaccess 的東西。

    當瀏覽器發送跨伺服器請求時,它首先發送 OPTIONS 請求以確保其有效並且可以發送「真實」請求。 當它從 OPTIONS 獲得正確且有效的回應後,才會發送「真正的」請求。

    現在,對於後端的兩個請求,您需要確保返回正確的標題:content-type、allow-origin、allow-headers 等...

    確保在後端的 OPTIONS 請求中,應用程式會傳回標頭並回傳回應,而不是繼續應用程式的完整流程。

    在「真實」請求中,您應該傳回正確的標頭和常規回應正文。

    範例:

    //The Response object
        $res = $app->response;
    
        $res->headers->set('Content-Type', 'application/json');
        $res->headers->set('Access-Control-Allow-Origin', 'http://example.com');
        $res->headers->set('Access-Control-Allow-Credentials', 'true');
        $res->headers->set('Access-Control-Max-Age', '60');
        $res->headers->set('Access-Control-Allow-Headers', 'AccountKey,x-requested-with, Content-Type, origin, authorization, accept, client-security-token, host, date, cookie, cookie2');
        $res->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
    
        if ( ! $req->isOptions()) {
            // this continues the normal flow of the app, and will return the proper body
            $this->next->call();
        } else {
            //stops the app, and sends the response
            return $res;
        }

    要記住的事:

    • 如果您使用:「Access-Control-Allow-Credentials」= true 確保“Access-Control-Allow-Origin”不是“*”,它必須設定正確的網域! (這裡流了很多血:/)

    • #定義您將在「Access-Control-Allow-Headers」中獲得的允許標頭 如果您不定義它們,請求將失敗

    • 如果您使用“Authorization: Bearer”,那麼“Access-Control-Allow-Headers”也應包含“Authorization”,否則請求將失敗

    回覆
    0
  • 取消回覆