PHP:检查URL是否重定向?

问题描述:

我已经在每个页面上实现了一个我想限制未登录用户的函数。该功能自动将访问者重定向到他或她未登录的情况下的登录页面。PHP:检查URL是否重定向?

我想使一个PHP函数从外部服务器运行并遍历多个设置的URL(数组包含每个受保护站点的URL)以查看它们是否被重定向。因此,我可以轻松确定每个页面上的防护是否已启动并运行。

这怎么办?

谢谢。

+0

重定向怎么样?从什么客户调用?登录时或未登录时?做什么的?脚本是否必须处理会话cookie和其他复杂的事情? – 2010-06-03 10:02:17

+0

请定义“重定向的URL”。 – 2010-06-03 10:02:38

+0

请参阅[如何确定URL是否在PHP中重定向?](http://*.com/questions/427203/how-can-i-determine-if-a-url-redirects-in-php/481377# 481377) – 2010-06-03 10:02:54

$urls = array(
    'http://www.apple.com/imac', 
    'http://www.google.com/' 
); 

$ch = curl_init(); 

curl_setopt($ch, CURLOPT_HEADER, true); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 

foreach($urls as $url) { 
    curl_setopt($ch, CURLOPT_URL, $url); 
    $out = curl_exec($ch); 

    // line endings is the wonkiest piece of this whole thing 
    $out = str_replace("\r", "", $out); 

    // only look at the headers 
    $headers_end = strpos($out, "\n\n"); 
    if($headers_end !== false) { 
     $out = substr($out, 0, $headers_end); 
    } 

    $headers = explode("\n", $out); 
    foreach($headers as $header) { 
     if(substr($header, 0, 10) == "Location: ") { 
      $target = substr($header, 10); 

      echo "[$url] redirects to [$target]<br>"; 
      continue 2; 
     } 
    } 

    echo "[$url] does not redirect<br>"; 
} 
+0

超级甜蜜的解决方案! Tack Adam :) – Industrial 2010-06-03 11:12:06

+2

您还可以使用curl_getinfo($ ch,CURLINFO_HTTP_CODE)来读取状态码(301或302) – baloo 2010-06-03 12:11:10

+2

如果您使用'curl_setopt($ handle,CURLOPT_NOBODY,true),您还可以节省一些带宽和处理能力。 '。这只会发送一个HTTP HEAD请求。这样你就不必切断身体。另请参阅此文章:http://schlitt.info/opensource/blog/0606_sending_head_requests_with_extcurl.html – chiborg 2012-04-26 21:25:28

我不明白你的问题。 你有一个包含URL的数组,你想知道用户是否来自某个列出的URL? 如果我正确理解你的追求:

$urls = array('http://url1.com','http://url2.ru','http://url3.org'); 
if(in_array($_SERVER['HTTP_REFERER'],$urls)) 
{ 
echo 'FROM ARRAY'; 
} else { 
echo 'NOT FROM ARR'; 
} 
+0

推举者很弱 – 2010-06-03 10:12:15

+0

更新了问题。我想调用数组中的每个url来查看它们是否停留在set url或重定向到登录页面。 – Industrial 2010-06-03 10:14:27

您可以使用会话,如果会话阵列没有设置,该URL重定向到一个登录页面。 。

+0

这就是我的安全基础,但不会让我能够看到一个数组中的页面是否重定向。 – Industrial 2010-06-03 10:15:52

我不确定这是否真的作为安全检查有意义。

如果你担心文件被直接调用而没有你的“用户登录?”检查正在运行,您可以执行许多大型PHP项目所做的事情:在*包含文件(安全检查正在进行)中定义一个常数BOOTSTRAP_LOADED或其他内容,并在每个文件中检查是否设置了该常量。

测试非常好,安全测试甚至更好,但我不确定您想要发现哪种缺陷?对我而言,这个想法感觉像是浪费时间,不会带来任何真正的额外安全。

只要确保您的脚本die() s在header("Location:...")之后重定向。这对于阻止额外的内容在标题命令之后显示是必不可少的(因为重定向标题仍将被发出,所以缺少die()将不会被您的想法所捕获...)

如果你真的想要这样做,你也可以使用像wget这样的工具并为它提供一个URL列表。让它将结果提取到一个目录中,然后检查(例如,通过查看应该相同的文件大小)每个页面是否包含登录对话框。只是添加另一个选项...

是否要检查HTTP代码以查看它是否是重定向?

$params = array('http' => array(
     'method' => 'HEAD', 
     'ignore_errors' => true 
    )); 

    $context = stream_context_create($params); 
    foreach(array('http://google.com', 'http://*.com') as $url) { 
     $fp = fopen($url, 'rb', false, $context); 
     $result = stream_get_contents($fp); 

     if ($result === false) { 
      throw new Exception("Could not read data from {$url}"); 
     } else if (! strstr($http_response_header[0], '301')) { 
      // Do something here 
     } 
    } 

我修改了Adam Backstrom的答案并实现了chiborg建议。 (只下载HEAD)。它还有一件事:它会检查重定向是在同一台服务器的一个页面上还是不存在。例如:terra.com.br重定向到terra.com.br/portal。 PHP会像重定向一样考虑它,并且它是正确的。但我只想列出重定向到另一个URL的那个URL。我的英语不好,所以,如果有人发现了一些很难理解的东西,并且可以编辑它,那么欢迎您。

function RedirectURL() { 
    $urls = array('http://www.terra.com.br/','http://www.areiaebrita.com.br/'); 

    foreach ($urls as $url) { 
     $ch = curl_init(); 

     curl_setopt($ch, CURLOPT_HEADER, true); 
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
     // chiborg suggestion 
     curl_setopt($ch, CURLOPT_NOBODY, true); 

     // ================================ 
     // READ URL 
     // ================================ 

     curl_setopt($ch, CURLOPT_URL, $url); 
     $out = curl_exec($ch); 

     // line endings is the wonkiest piece of this whole thing 
     $out = str_replace("\r", "", $out); 
     echo $out; 

     $headers = explode("\n", $out); 

     foreach($headers as $header) { 
      if(substr(strtolower($header), 0, 9) == "location:") { 
       // read URL to check if redirect to somepage on the server or another one. 
       // terra.com.br redirect to terra.com.br/portal. it is valid. 
       // but areiaebrita.com.br redirect to bwnet.com.br, and this is invalid. 
       // what we want is to check if the address continues being terra.com.br or changes. if changes, prints on page. 

       // if contains http, we will check if changes url or not. 
       // some servers, to redirect to a folder available on it, redirect only citting the folder. Example: net11.com.br redirect only to /heiden 

       // only execute if have http on location 
       if (strpos(strtolower($header), "http") !== false) { 
        $address = explode("/", $header); 

        print_r($address); 
        // $address['0'] = http 
        // $address['1'] = 
        // $address['2'] = www.terra.com.br 
        // $address['3'] = portal 

        echo "url (address from array) = " . $url . "<br>"; 
        echo "address[2] = " . $address['2'] . "<br><br>"; 

        // url: terra.com.br 
        // address['2'] = www.terra.com.br 

        // check if string terra.com.br is still available in www.terra.com.br. It indicates that server did not redirect to some page away from here. 
        if(strpos(strtolower($address['2']), strtolower($url)) !== false) { 
         echo "URL NOT REDIRECT"; 
        } else { 
         // not the same. (areiaebrita) 
         echo "SORRY, URL REDIRECT WAS FOUND: " . $url; 
        } 
       } 
      } 
     } 
    } 
} 

function unshorten_url($url){ 
    $ch = curl_init(); 

    curl_setopt($ch, CURLOPT_HEADER, true); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
    curl_setopt($ch, CURLOPT_URL, $url); 
    $out = curl_exec($ch); 

    $real_url = $url;//default.. (if no redirect) 

    if (preg_match("/location: (.*)/i", $out, $redirect)) 
     $real_url = $redirect[1]; 

    if (strstr($real_url, "bit.ly"))//the redirect is another shortened url 
     $real_url = unshorten_url($real_url); 

    return $real_url; 
} 

你总是可以尝试添加:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 

,因为302是指它移动,使卷曲呼叫跟踪,并返回无论移动网址的回报。

+0

这......实际上是正确的答案。谢谢!看起来如果没有这个curl就会停止它首先收到的内容,并且如果有的话就不会遵循重定向。谢谢!!! – 2014-08-23 04:21:47

我用卷曲,只需要头,之后我比较我的网址和URL的头卷曲:

   $url="http://google.com"; 
       $ch = curl_init(); 

       curl_setopt($ch, CURLOPT_URL, $url); 
       curl_setopt($ch, CURLOPT_TIMEOUT, '60'); // in seconds 
       curl_setopt($ch, CURLOPT_HEADER, 1); 
       curl_setopt($ch, CURLOPT_NOBODY, 1); 
       curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 
       curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
       $res = curl_exec($ch); 

       if(curl_getinfo($ch)['url'] == $url){ 
        $status = "not redirect"; 
       }else { 
        $status = "redirect"; 
       }