搜索

首页  >  问答  >  正文

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.用户名 + ':' + login.密码));
    返回 this.http.post(this.apiBaseUrl + '/Account/Login', "grant_type=client_credentials", { headers: headers })
        .map(响应=>{
            // 代码
        });
}</pre>

<p>如果我通过邮递员运行请求(这不会影响 CORS),我会得到:</p>

<pre class="brush:php;toolbar:false;">{ "error": "invalid_client", "error_description": "在标头或正文中找不到客户端凭据" }</pre>

<p>我尝试将 origin 设置为 '*' 只是为了测试并查看这是否是问题的核心,但它仍然以同样的方式失败。</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 天前691

全部回复(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
  • 取消回复