2010-06-03 114 views
7

我已經在每個頁面上實現了一個我想限制未登錄用戶的函數。該功能自動將訪問者重定向到他或她未登錄的情況下的登錄頁面。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://stackoverflow.com/questions/427203/how-can-i-determine-if-a-url-redirects-in-php/481377# 481377) – 2010-06-03 10:02:54

回答

21
$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

-2

我不明白你的問題。 你有一個包含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

0

您可以使用會話,如果會話陣列沒有設置,該URL重定向到一個登錄頁面。 。

+0

這就是我的安全基礎,但不會讓我能夠看到一個數組中的頁面是否重定向。 – Industrial 2010-06-03 10:15:52

1

我不確定這是否真的作爲安全檢查有意義。

如果你擔心文件被直接調用而沒有你的「用戶登錄?」檢查正在運行,您可以執行許多大型PHP項目所做的事情:在中央包含文件(安全檢查正在進行)中定義一個常數BOOTSTRAP_LOADED或其他內容,並在每個文件中檢查是否設置了該常量。

測試非常好,安全測試甚至更好,但我不確定您想要發現哪種缺陷?對我而言,這個想法感覺像是浪費時間,不會帶來任何真正的額外安全。

只要確保您的腳本die() s在header("Location:...")之後重定向。這對於阻止額外的內容在標題命令之後顯示是必不可少的(因爲重定向標題仍將被髮出,所以缺少die()將不會被您的想法所捕獲...)

如果你真的想要這樣做,你也可以使用像wget這樣的工具併爲它提供一個URL列表。讓它將結果提取到一個目錄中,然後檢查(例如,通過查看應該相同的文件大小)每個頁面是否包含登錄對話框。只是添加另一個選項...

1

是否要檢查HTTP代碼以查看它是否是重定向?

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

    $context = stream_context_create($params); 
    foreach(array('http://google.com', 'http://stackoverflow.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 
     } 
    } 
0

我修改了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; 
        } 
       } 
      } 
     } 
    } 
} 
0
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; 
} 
2

你總是可以嘗試添加:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 

,因爲302是指它移動,使捲曲呼叫跟蹤,並返回無論移動網址的回報。

+0

這......實際上是正確的答案。謝謝!看起來如果沒有這個curl就會停止它首先收到的內容,並且如果有的話就不會遵循重定向。謝謝!!! – 2014-08-23 04:21:47

3

我用捲曲,只需要頭,之後我比較我的網址和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"; 
       }