簡體   English   中英

PHP:檢查 URL 是否重定向?

[英]PHP: Check if URL redirects?

我已經實現了一個在每個頁面上運行的功能,我想限制非登錄用戶。 該功能在訪問者未登錄的情況下自動將訪問者重定向到登錄頁面。

我想創建一個從外部服務器運行的 PHP 函數,並遍歷多個設置的 URL(帶有每個受保護站點的 URL 的數組)以查看它們是否被重定向。 因此,我可以輕松確定保護是否已在每個頁面上啟動並運行。

這怎么可能?

謝謝。

$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>";
}

在比較我的 url 和來自 header curl 的 url 之后,我使用 curl 並且只使用 headers:

                $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){
                    echo "not redirect";
                }else {
                    echo "redirect";
                }

您可以隨時嘗試添加:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 

因為 302 意味着它移動了,允許 curl 調用跟隨它並返回移動的 url 返回的任何內容。

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

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

測試很棒,安全測試甚至更好,但我不確定您希望通過此發現什么樣的缺陷? 對我來說,這個想法感覺像是浪費時間,不會帶來任何真正的額外安全性。

只需確保您的腳本die()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://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
      }
    }

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

您可以使用會話,如果會話數組未設置,則 url 重定向到登錄頁面。 .

我剛剛做了一個檢查 URL 是否存在的函數

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

function url_exists($url, $ch) {
   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);
   }   
   //echo $out."====<br>";
   $headers = explode("\n", $out);
   //echo "<pre>";
   //print_r($headers);
   foreach($headers as $header) {
       //echo $header."---<br>";
       if( strpos($header, 'HTTP/1.1 200 OK') !== false ) { 
          return true;
          break;
       }
   }  

}

現在我使用了一組 URL 來檢查 URL 是否存在,如下所示:

$my_url_array = array('http://howtocode.pk/result', 'http://google.com/jobssss', 'https://howtocode.pk/javascript-tutorial/', 'https://www.google.com/');

for($j = 0; $j < count($my_url_array); $j++){

      if(url_exists($my_url_array[$j], $ch)){
           echo 'This URL "'.$my_url_array[$j].'" exists. <br>';
      }
}

我希望它能幫助你:

function checkRedirect($url)
{
        $headers = get_headers($url);
        if ($headers) {
            if (isset($headers[0])) {
                if ($headers[0] == 'HTTP/1.1 302 Found') {
                    //this is the URL where it's redirecting
                    return str_replace("Location: ", "", $headers[9]);
                }
            }
        }
        return false;
}
$isRedirect = checkRedirect($url);
if(!$isRedirect )
{
   echo "URL Not Redirected";
}else{
   echo "URL Redirected to: ".$isRedirect;
}

使用get_headers()獲取標頭並檢查Location是否設置要簡單得多。

$urls = [
    "https://example-1.com",
    "https://example-2.com"
];

foreach ($urls as $key => $url) {

    $is_redirect = does_url_redirect($url) ? 'yes' : 'no';
    echo $url . ' is redirected: ' . $is_redirect . PHP_EOL;
}

function does_url_redirect($url){
    
    $headers = get_headers($url, 1);
    if (!empty($headers['Location'])) {
        return true;
    } else {
        return false;
    }
}

我無法理解你的問題。 您有一個包含 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';
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM