PHP:检查 URL 是否重定向?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2964834/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 08:16:09  来源:igfitidea点击:

PHP: Check if URL redirects?

phpfunctionredirectcurl

提问by Industrial

I have implemented a function that runs on each page that I want to restrict from non-logged in users. The function automatically redirects the visitor to the login page in the case of he or she is not logged in.

我已经实现了一个在每个页面上运行的功能,我想限制非登录用户。该功能在访问者未登录的情况下自动将访问者重定向到登录页面。

I would like to make a PHP function that is run from a exernal server and iterates through a number of set URLs (array with URLs that is for each protected site) to see if they are redirected or not. Thereby I could easily make sure if protection is up and running on every page.

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

How could this be done?

这怎么可能?

Thanks.

谢谢。

回答by Annika Backstrom

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

回答by Piotr Kazu?

I use curl and only take headers, after I compare my url and url from header curl:

在比较我的 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";
                }

回答by Bren1818

You could always try adding:

您可以随时尝试添加:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 

since 302 means it moved, allow the curl call to follow it and return whatever the moved url returns.

因为 302 意味着它移动了,允许 curl 调用跟随它并返回移动的 url 返回的任何内容。

回答by Pekka

I'm not sure whether this really makes sense as a security check.

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

If you are worried about files getting called directly without your "is the user logged in?" checks being run, you could do what many big PHP projects do: In the central include file (where the security check is being done) define a constant BOOTSTRAP_LOADEDor whatever, and in every file, check for whether that constant is set.

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

Testing is great and security testing is even better, but I'm not sure what kind of flaw you are looking to uncover with this? To me, this idea feels like a waste of time that will not bring any real additional security.

测试很棒,安全测试甚至更好,但我不确定您希望通过此发现什么样的缺陷?对我来说,这个想法感觉像是浪费时间,不会带来任何真正的额外安全。

Just make sure your script die()s after the header("Location:...")redirect. That is essential to stop additional content from being displayed after the header command (a missing die() wouldn't be caught by your idea by the way, as the redirect header would still be issued...)

只需确保您的脚本die()header("Location:...")重定向之后。这对于阻止在标题命令之后显示其他内容至关重要(顺便说一下,您的想法不会捕获丢失的 die(),因为仍然会发出重定向标题...)

If you really want to do this, you could also use a tool like wgetand feed it a list of URLs. Have it fetch the results into a directory, and check (e.g. by looking at the file sizes that should be identical) whether every page contains the login dialog. Just to add another option...

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

回答by baloo

Do you want to check the HTTP code to see if it's a redirect?

是否要检查 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
      }
    }

回答by jaysponsored

I modified Adam Backstrom answer and implemented chiborg suggestion. (Download only HEAD). It have one thing more: It will check if redirection is in a page of the same server or is out. Example: terra.com.br redirects to terra.com.br/portal. PHP will considerate it like redirect, and it is correct. But i only wanted to list that url that redirect to another URL. My English is not good, so, if someone found something really difficult to understand and can edit this, you're welcome.

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

回答by Ludo - Off the record

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

回答by luckydeng

You can use session,if the session array is not set ,the url redirected to a login page. .

您可以使用会话,如果会话数组未设置,则 url 重定向到登录页面。.

回答by Safeer Ahmed

I have just made a function that checks if a URL exists or not

我刚刚做了一个检查 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;
       }
   }  

}

Now I have used an array of URLs to check if a URL exists as following:

现在我使用了一组 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>';
      }
}

回答by Shahzaib Chadhar

I hope it will help you:

我希望它能帮助你:

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