2010-06-03 5 views
7

Я реализовал функцию, которая запускается на каждой странице, которую я хочу ограничить от не зарегистрированных пользователей. Функция автоматически перенаправляет посетителя на страницу входа в систему, если он или она не вошли в систему.PHP: Проверьте, перенаправляется ли URL?

Я хотел бы сделать функцию PHP, которая запускается с внешнего сервера и выполняет итерацию по множеству заданных URL (массив с URL-адресами для каждого защищенного сайта), чтобы увидеть, перенаправлены ли они или нет. Таким образом, я мог бы легко убедиться, что защита включена и запущена на каждой странице.

Как это можно сделать?

Спасибо.

+0

Перенаправление как? Вызывается от какого клиента? При входе или при входе в систему? Зачем? Будет ли скрипт обрабатывать сеансовые куки и другие сложные вещи? –

+0

Определите «перенаправленный URL», пожалуйста. –

+0

См. [Как определить, перенаправляется ли URL в PHP?] (Http://stackoverflow.com/questions/427203/how-can-i-determine-if-a-url-redirects-in-php/481377# 481377) –

ответ

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

+2

Вы также можете использовать curl_getinfo ($ ch, CURLINFO_HTTP_CODE) для чтения кода состояния (301 или 302). – baloo

+2

Вы также можете сэкономить некоторую пропускную способность и вычислительную мощность, если вы используете 'curl_setopt ($ handle, CURLOPT_NOBODY, true); '. Это отправит запрос HTTP HEAD. Таким образом, вам не придется отрезать тело. См. Также эту статью: http://schlitt.info/opensource/blog/0606_sending_head_requests_with_extcurl.html – chiborg

-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

рефери слабый –

+0

Обновлен вопрос. Я хочу вызвать каждый URL-адрес в моем массиве, чтобы посмотреть, остаются ли они на заданном URL-адресе или перенаправляются на страницу входа. – Industrial

0

Вы можете использовать сеанс, если массив сеанса не установлен, URL перенаправлены на страницу входа в систему. .

+0

Вот как моя безопасность основана в основном, но не заставит меня видеть, перенаправляет ли страница из массива или нет. – Industrial

1

Я не уверен, действительно ли это имеет смысл в качестве проверки безопасности.

Если вы беспокоитесь о том, что файлы, вызываемые напрямую, без вашего участия, являются ли ваши пользователи? проверки выполняются, вы можете сделать то, что делают многие большие проекты PHP: в центральном файле include (где выполняется проверка безопасности) определите константу 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

Я изменил ответ Адама Backstrom и внедрил предложение чиборга. (Только для загрузки 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 означает, что он переехал, дайте локон вызов следовать за ним и вернуться независимо от конкретных перемещаемых возвращает URL.

+0

ЭТО ... на самом деле правильный ответ. Спасибо! Похоже, что без этого завитка останавливается на контенте, который он сначала получает и не выполняет перенаправление, если он есть. Спасибо!!! –

3

Я использую локон и принимать только заголовки, после того, как я сравниваю свой URL и 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"; 
       } 
Смежные вопросы