Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 指定具有访问控制源的多个子域_Php_Javascript_Ajax_Header_Cross Domain - Fatal编程技术网

Php 指定具有访问控制源的多个子域

Php 指定具有访问控制源的多个子域,php,javascript,ajax,header,cross-domain,Php,Javascript,Ajax,Header,Cross Domain,我试图允许访问我站点上的每个子域,以便允许跨子域AJAX调用。是否有一种方法可以指定网站的所有子域,如*.example.com,或者,当我列出了多个域时,为什么以下方法不起作用: header('Access-Control-Allow-Origin: http://api.example.com http://www.example.com'); 我已经通读了下面的问题,这个问题看起来很相似,如果不是和这个问题相同的话,除了我想访问子域这个问题是指一般的域 如果上面的问题是这个问题的解决

我试图允许访问我站点上的每个子域,以便允许跨子域AJAX调用。是否有一种方法可以指定网站的所有子域,如
*.example.com
,或者,当我列出了多个域时,为什么以下方法不起作用:

header('Access-Control-Allow-Origin: http://api.example.com http://www.example.com');
我已经通读了下面的问题,这个问题看起来很相似,如果不是和这个问题相同的话,除了我想访问子域这个问题是指一般的域


如果上面的问题是这个问题的解决方案,那么我如何能够从标题中检索原点。看来$\u服务器['HTTP\u ORIGIN']非常不可靠,甚至不跨浏览器。我需要能够在尝试使用javascript发送AJAX调用时显示错误的任何浏览器中查看源代码。

解决此问题的方法是使用
$\u服务器['HTTP\u origin']
变量来确定请求是否来自允许的域,然后有条件地设置
访问控制允许原点
,如下所示:

$allowed_domains = [/* Array of allowed domains*/];

if (in_array($_SERVER['HTTP_ORIGIN'], $allowed_domains)) {
    header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
}

虽然答案有效,但它确实违背了整个事情的目的,因为它允许来自任何主机的请求

我用的是:

if(isset($_SERVER['HTTP_ORIGIN'])) {
  $origin = $_SERVER['HTTP_ORIGIN'];
  if($origin == 'https://sub1.my-website.com' OR $origin == 'https://sub2.my-website.com') {
    header("Access-Control-Allow-Origin: $origin");
  }
}

我尝试使用这种方法在特定领域实现约束:

$allowed_origin = '';
$parts = explode('.', parse_url($_SERVER['HTTP_HOST'])['host']);
if(end($parts).".".prev($parts) === "com.domain") {
    $allowed_origin = $_SERVER['HTTP_ORIGIN'];
    header('Acesss-Control-Allow-Origin: '. $allowed_origin);
}
我希望它能起作用。

我是这样做的

Origin
头由浏览器指定,将包含在其他域上请求脚本的域:

Origin: http://www.websiteA.com
因此,您可以在服务器端脚本中“白名单”多个域:

$allowedOrigins = [
    "http://www.websiteA.com",
    "https://www.websiteB.com"
    // ... etc
];
然后,您可以检查
$\u服务器[“HTTP\u ORIGIN”]
全局是否包含该白名单中的域:

if (in_array($_SERVER["HTTP_ORIGIN"], $allowedOrigins)) {
并将
Access Control Allow Origin
响应头设置为
Origin
头值为:

header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"]);
完整脚本:

$allowedOrigins = [
    "http://www.websiteA.com",
    "https://www.websiteB.com"
    // ... etc
];

if (in_array($_SERVER["HTTP_ORIGIN"], $allowedOrigins)) {
    header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"]);
}

如果你想要通配符域,我认为这更有效

if(isset($_SERVER['HTTP_ORIGIN']) && preg_match('!^http(s)?://([a-z0-9\-]+\.)?example.com$!is', $_SERVER['HTTP_ORIGIN']))
{
    header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
}

这是我的挑战和解决方案:

function getSubDomain(){
    
    let mySubDomain = "";
    
    let myDomain = window.location.host;
    let myArrayParts = myDomain.split(".");
    if (myArrayParts.length == 3){
        mySubDomain = myArrayParts[0];
    }
    
    return mySubDomain;
    
}
1-api.example.com上的后端PHP

2-多个JS前端,如one.example.com、two.example.com等

3-Cookie需要双向传递

4-在api.example.com上从多个前端到PHP后端的AJAX调用

5-在PHP中,我不喜欢使用$_SERVER[“HTTP_ORIGIN”],在我看来并不总是可靠/安全的(我有一些浏览器HTTP-ORIGIN总是空的)

在具有单个前端域的PHP中执行此操作的常规方法是使用以下代码启动PHP代码:

header('Access-Control-Allow-Origin: https://one.example.com');  
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');  
header('Access-Control-Allow-Credentials: true');  
在one.example.com域的JS中:

jQuery.ajax({
    url: myURL,
    type: "POST",
    xhrFields: {withCredentials: true},
    dataType: "text",
    contentType: "text/xml; charset=\"utf-8\"",
    cache: false,
    headers: "",
    data: myCallJSONStr,
    success: function(myResponse) {.....}
但是,这是不可行的,因为我使用多个子域来调用我的API域

由于我想传递cookies,此解决方案将不起作用:

header('Access-Control-Allow-Origin: *');  
它与JS站点上的传递cookie设置冲突:

xhrFields: {withCredentials: true}
以下是我所做的:

1-使用GET参数传递子域。 2-在PHP中硬编码主域,因此只允许(所有)子域

这是我的解决方案的JS/JQuery AJAX部分:

function getSubDomain(){
    
    let mySubDomain = "";
    
    let myDomain = window.location.host;
    let myArrayParts = myDomain.split(".");
    if (myArrayParts.length == 3){
        mySubDomain = myArrayParts[0];
    }
    
    return mySubDomain;
    
}
在AJAX调用中:

    let mySubDomain = getSubDomain();
    if (mySubDomain != ""){
        myURL += "?source=" + mySubDomain + "&end"; //use & instead of ? if URL already has GET parameters
    }
    
    jQuery.ajax({
        url: myURL,
        type: "POST",
        xhrFields: {withCredentials: true},
        dataType: "text",
        contentType: "text/xml; charset=\"utf-8\"",
        cache: false,
        headers: "",
        data: myCallJSONStr,
        success: function(myResponse) {.....}
最后,PHP部分:

<?php

$myDomain = "example.com";
$mySubdomain = "";

if (isset($_GET["source"])) {
    $mySubdomain = $_GET["source"].".";
}

$myDomainAllowOrigin = "https://".$mySubdomain.$myDomain;
$myAllowOrigin = "Access-Control-Allow-Origin: ".$myDomainAllowOrigin;

//echo $myAllowOrigin;

header($myAllowOrigin);  
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');  
header('Access-Control-Allow-Credentials: true');

正如您所说,您问题的第一部分已在链接中得到回答。关于第二个问题:如果浏览器尝试跨域策略禁止的Ajax调用,请求将失败,根本无法到达服务器。此错误必须在浏览器中处理。我知道我将收到一个错误,但此错误将在调用尝试访问外部文件后提供。如果文件拒绝它,则会抛出错误。如果我将标题设置为允许访问所有内容,那么它将起作用,但这对我来说太开放了,因此我希望将其设置为与请求的来源相关。因此,我想知道如何使用PHP获取请求的来源。您能否详细说明一下“$\u服务器['HTTP\u origin']非常不可靠,甚至不跨浏览器”的含义$_服务器['HTTP_ORIGIN']是一个服务器端值,不会在浏览器中执行。是的,我同意,并且对它不兼容跨浏览器感到有些困惑,但我在另一个问题上看到了这一点。我从来没有听说过HTTP_ORIGIN,只有在我能确定它在所有浏览器中都能工作的情况下才想使用它。
$_SERVER['HTTP_ORIGIN')
并不总是可用,这取决于浏览器。你可以用:
如果(array_key_存在('HTTP_ORIGIN',$_SERVER)){$ORIGIN$_SERVER['HTTP_ORIGIN]}或者如果(array_key_存在)('HTTP_REFERER',$_SERVER)){$origin=$_SERVER['HTTP_REFERER'];}其他{$origin=$_SERVER['REMOTE_ADDR'];}
<?php

    //////////////// GLOBALS /////////////////////////////////
    
    $gCookieDomain = ".example.com";
    $gCookieValidForDays = 90;
    
    //////////////// COOKIE FUNTIONS /////////////////////////////////
    
    function setAPCookie($myCookieName, $myCookieValue, $myHttponly){
        global $gCookieDomain;
        global $gCookieValidForDays;
        
        $myExpires = time()+60*60*24*$gCookieValidForDays;
        setcookie($myCookieName, $myCookieValue, $myExpires, "/", $gCookieDomain, true, $myHttponly);   
        
        return $myExpires;
    }
<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "https://one.example.com"
    Header set Access-Control-Allow-Headers "Origin, Content-Type, X-Auth-Token"
    Header set Access-Control-Allow-Credentials "true"
</IfModule>