PHP 卷曲和饼干

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12885538/
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 04:25:59  来源:igfitidea点击:

PHP Curl And Cookies

phpauthenticationcookiescurl

提问by Shark

I have some problem with PHP Curl and cookies authentication.

我对 PHP Curl 和 cookie 身份验证有一些问题。

I have a file Connector.phpwhich authenticates users on another server and returns the cookie of the current user.

我有一个文件Connector.php,它验证另一台服务器上的用户并返回当前用户的 cookie。

The Problem is that I want to authenticate thousands of users with curl but it authenticates and saves COOKIES only for one user at a time.

问题是我想使用 curl 对数千名用户进行身份验证,但它一次仅对一个用户进行身份验证并保存 COOKIES。

The code for connector.php is this:

connector.php 的代码是这样的:

    <?php
    if(!count($_REQUEST)) {
        die("No Access!");
    }


    //Core Url For Services
    define ('ServiceCore', 'http://example.com/core/');


    //Which Internal Service Should Be Called
    $path = $_GET['service'];


    //Service To Be Queried
    $url = ServiceCore.$path;

    //Open the Curl session
    $session = curl_init($url);

    // If it's a GET, put the GET data in the body
    if ($_GET['service']) {
        //Iterate Over GET Vars
        $postvars = '';
        foreach($_GET as $key=>$val) {
            if($key!='service') {
                $postvars.="$key=$val&";
            }
        }
        curl_setopt ($session, CURLOPT_POST, true);
        curl_setopt ($session, CURLOPT_POSTFIELDS, $postvars);
    }


    //Create And Save Cookies
    $tmpfname = dirname(__FILE__).'/cookie.txt';
    curl_setopt($session, CURLOPT_COOKIEJAR, $tmpfname);
    curl_setopt($session, CURLOPT_COOKIEFILE, $tmpfname);

    curl_setopt($session, CURLOPT_HEADER, false);
    curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($session, CURLOPT_FOLLOWLOCATION, true);

    // EXECUTE
    $json = curl_exec($session);
        echo $json;
    curl_close($session);
?>

Here is the process of authentication:

下面是认证过程:

  1. User enters username and password: Connector.php?service=logon&user_name=user32&user_pass=123
  2. Connector.php?service=logosessionInforeturns info about the user based on the cookies saved earlier with logon service.
  1. 用户输入用户名和密码: Connector.php?service=logon&user_name=user32&user_pass=123
  2. Connector.php?service=logosessionInfo根据先前使用登录服务保存的 cookie 返回有关用户的信息。

The problem is that this code saves the cookie in one file for each user and can't handle multiple user authentications.

问题是此代码将 cookie 保存在每个用户的一个文件中,并且无法处理多个用户身份验证。

采纳答案by Shark

Solutions which are described above, even with unique CookieFile names, can cause a lot of problems on scale.

上面描述的解决方案,即使使用唯一的 CookieFile 名称,也会在规模上导致很多问题。

We had to serve a lot of authentications with this solution and our server went down because of high file read write actions.

我们必须使用此解决方案提供大量身份验证,并且由于大量文件读写操作,我们的服务器出现故障。

The solution for this was to use Apache Reverse Proxy and omit CURL requests at all.

对此的解决方案是使用 Apache 反向代理并完全忽略 CURL 请求。

Details how to use Proxy on Apache can be found here: https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html

可以在此处找到如何在 Apache 上使用代理的详细信息:https: //httpd.apache.org/docs/2.4/howto/reverse_proxy.html

回答by Adam

You can specify the cookie file with a curl opt. You could use a unique file for each user.

您可以使用 curl opt 指定 cookie 文件。您可以为每个用户使用唯一的文件。

curl_setopt( $curl_handle, CURLOPT_COOKIESESSION, true );
curl_setopt( $curl_handle, CURLOPT_COOKIEJAR, uniquefilename );
curl_setopt( $curl_handle, CURLOPT_COOKIEFILE, uniquefilename );

The best way to handle it would be to stick your request logic into a curl function and just pass the unique file name in as a parameter.

处理它的最佳方法是将您的请求逻辑粘贴到 curl 函数中,并将唯一的文件名作为参数传入。

    function fetch( $url, $z=null ) {
            $ch =  curl_init();

            $useragent = isset($z['useragent']) ? $z['useragent'] : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2';

            curl_setopt( $ch, CURLOPT_URL, $url );
            curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
            curl_setopt( $ch, CURLOPT_AUTOREFERER, true );
            curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
            curl_setopt( $ch, CURLOPT_POST, isset($z['post']) );

            if( isset($z['post']) )         curl_setopt( $ch, CURLOPT_POSTFIELDS, $z['post'] );
            if( isset($z['refer']) )        curl_setopt( $ch, CURLOPT_REFERER, $z['refer'] );

            curl_setopt( $ch, CURLOPT_USERAGENT, $useragent );
            curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, ( isset($z['timeout']) ? $z['timeout'] : 5 ) );
            curl_setopt( $ch, CURLOPT_COOKIEJAR,  $z['cookiefile'] );
            curl_setopt( $ch, CURLOPT_COOKIEFILE, $z['cookiefile'] );

            $result = curl_exec( $ch );
            curl_close( $ch );
            return $result;
    }

I use this for quick grabs. It takes the url and an array of options.

我用它来快速抓取。它需要 url 和一组选项。

回答by Doug

In working with a similar problem I created the following function after combining a lot of resources I ran into on the web, and adding my own cookie handling. Hopefully this is useful to someone else.

在处理类似问题时,我在结合了我在网络上遇到的大量资源并添加了我自己的 cookie 处理后创建了以下函数。希望这对其他人有用。

      function get_web_page( $url, $cookiesIn = '' ){
        $options = array(
            CURLOPT_RETURNTRANSFER => true,     // return web page
            CURLOPT_HEADER         => true,     //return headers in addition to content
            CURLOPT_FOLLOWLOCATION => true,     // follow redirects
            CURLOPT_ENCODING       => "",       // handle all encodings
            CURLOPT_AUTOREFERER    => true,     // set referer on redirect
            CURLOPT_CONNECTTIMEOUT => 120,      // timeout on connect
            CURLOPT_TIMEOUT        => 120,      // timeout on response
            CURLOPT_MAXREDIRS      => 10,       // stop after 10 redirects
            CURLINFO_HEADER_OUT    => true,
            CURLOPT_SSL_VERIFYPEER => true,     // Validate SSL Certificates
            CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
            CURLOPT_COOKIE         => $cookiesIn
        );

        $ch      = curl_init( $url );
        curl_setopt_array( $ch, $options );
        $rough_content = curl_exec( $ch );
        $err     = curl_errno( $ch );
        $errmsg  = curl_error( $ch );
        $header  = curl_getinfo( $ch );
        curl_close( $ch );

        $header_content = substr($rough_content, 0, $header['header_size']);
        $body_content = trim(str_replace($header_content, '', $rough_content));
        $pattern = "#Set-Cookie:\s+(?<cookie>[^=]+=[^;]+)#m"; 
        preg_match_all($pattern, $header_content, $matches); 
        $cookiesOut = implode("; ", $matches['cookie']);

        $header['errno']   = $err;
        $header['errmsg']  = $errmsg;
        $header['headers']  = $header_content;
        $header['content'] = $body_content;
        $header['cookies'] = $cookiesOut;
    return $header;
}

回答by Marin Sagovac

First create temporary cookie using tempnam() function:

首先使用 tempnam() 函数创建临时 cookie:

$ckfile = tempnam ("/tmp", "CURLCOOKIE");

Then execute curl init witch saves the cookie as a temporary file:

然后执行 curl init 将 cookie 保存为临时文件:

$ch = curl_init ("http://uri.com/");
curl_setopt ($ch, CURLOPT_COOKIEJAR, $ckfile);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec ($ch);

Or visit a page using the cookie stored in the temporary file:

或者使用存储在临时文件中的 cookie 访问页面:

$ch = curl_init ("http://somedomain.com/cookiepage.php");
curl_setopt ($ch, CURLOPT_COOKIEFILE, $ckfile);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec ($ch);

This will initialize the cookie for the page:

这将初始化页面的 cookie:

curl_setopt ($ch, CURLOPT_COOKIEFILE, $ckfile);

回答by ewake

Here you can find some useful info about cURL & cookies http://docstore.mik.ua/orelly/webprog/pcook/ch11_04.htm.

在这里你可以找到一些关于 cURL 和 cookie 的有用信息http://docstore.mik.ua/orelly/webprog/pcook/ch11_04.htm

You can also use this well done method https://github.com/alixaxel/phunction/blob/master/phunction/Net.php#L89like a function:

您也可以像函数一样使用这个做得好的方法https://github.com/alixaxel/phunction/blob/master/phunction/Net.php#L89

function CURL($url, $data = null, $method = 'GET', $cookie = null, $options = null, $retries = 3)
{
    $result = false;

    if ((extension_loaded('curl') === true) && (is_resource($curl = curl_init()) === true))
    {
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_FAILONERROR, true);
        curl_setopt($curl, CURLOPT_AUTOREFERER, true);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

        if (preg_match('~^(?:DELETE|GET|HEAD|OPTIONS|POST|PUT)$~i', $method) > 0)
        {
            if (preg_match('~^(?:HEAD|OPTIONS)$~i', $method) > 0)
            {
                curl_setopt_array($curl, array(CURLOPT_HEADER => true, CURLOPT_NOBODY => true));
            }

            else if (preg_match('~^(?:POST|PUT)$~i', $method) > 0)
            {
                if (is_array($data) === true)
                {
                    foreach (preg_grep('~^@~', $data) as $key => $value)
                    {
                        $data[$key] = sprintf('@%s', rtrim(str_replace('\', '/', realpath(ltrim($value, '@'))), '/') . (is_dir(ltrim($value, '@')) ? '/' : ''));
                    }

                    if (count($data) != count($data, COUNT_RECURSIVE))
                    {
                        $data = http_build_query($data, '', '&');
                    }
                }

                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            }

            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));

            if (isset($cookie) === true)
            {
                curl_setopt_array($curl, array_fill_keys(array(CURLOPT_COOKIEJAR, CURLOPT_COOKIEFILE), strval($cookie)));
            }

            if ((intval(ini_get('safe_mode')) == 0) && (ini_set('open_basedir', null) !== false))
            {
                curl_setopt_array($curl, array(CURLOPT_MAXREDIRS => 5, CURLOPT_FOLLOWLOCATION => true));
            }

            if (is_array($options) === true)
            {
                curl_setopt_array($curl, $options);
            }

            for ($i = 1; $i <= $retries; ++$i)
            {
                $result = curl_exec($curl);

                if (($i == $retries) || ($result !== false))
                {
                    break;
                }

                usleep(pow(2, $i - 2) * 1000000);
            }
        }

        curl_close($curl);
    }

    return $result;
}

And pass this as $cookieparameter:

并将其作为$cookie参数传递:

$cookie_jar = tempnam('/tmp','cookie');

回答by s.webbandit

You can define different cookies for every user with CURLOPT_COOKIEFILEand CURLOPT_COOKIEJAR. Make different file for every user so each one would have it's own cookie-based session on remote server.

您可以使用CURLOPT_COOKIEFILE和为每个用户定义不同的 cookie CURLOPT_COOKIEJAR。为每个用户制作不同的文件,这样每个用户都会在远程服务器上拥有自己的基于 cookie 的会话。