2012-10-14 8 views
26

PHPカールとクッキー認証に問題があります。PHPカールとクッキー

私はファイルを持っています。Connector.phpは、別のサーバー上のユーザーを認証し、現在のユーザーでCookieを返します。

問題は、何千ものユーザーをカールで認証したいが、一度に1人のユーザーに対してのみCookieを認証して保存するということです。

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); 
?> 

は認証のプロセスです:

  1. ユーザーは、ユーザー名とパスワードを入力:Connector.phpサービス=ログオン& USER_NAME =? user32 & user_pass = 123
  2. Connector.php?service = logosessionInfoこれは、ログオンサービスで先に保存されたクッキーに基づいてユーザーに関する情報を返します。

このコードはCookieを1人のユーザーに1つのファイルに保存し、複数のユーザー認証を処理できないという問題があります。

+2

私はユニークPHPSESSIDを持つユーザごとに異なるCookieファイルを作成して私の問題を解決しました。 '$ tmpfname = dirname(__ FILE __)。 '/'。$ _ COOKIE ['PHPSESSID']。 '。txt'; ' – Shark

+0

はユーザー数が多い場合には良いアイデアですか? – trainoasis

+0

いいえ多くのユーザーがいる場合、これは悪いです。これは、Apacheサーバーのクラッシュを引き起こします。私はこの問題をApacheのプロキシで解決します。すべてのCURLコードを削除しました。 – Shark

答えて

0

ソリューション、大規模な問題を引き起こす可能性があります。

このソリューションでは多くの認証を処理する必要があり、ファイルの読み取り書き込み操作が多いため、サーバーがダウンしました。

解決策は、Apache Reverse Proxyを使用し、CURLリクエストをまったく省略することでした。 Apacheの上でプロキシを使用する方法

詳細はここで見つけることができます: https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html

22

cookieファイルをcurl optで指定できます。ユーザーごとに一意のファイルを使用できます。

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

これを処理する最善の方法は、リクエストロジックをカール関数に張り、パラメータとして一意のファイル名を渡すことです。

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

私はこれを迅速なグラブに使用します。それはURLとオプションの配列をとります。

+0

ありがとう、私の問題を解決! – user3236289

1

CURLOPT_COOKIEFILEとを使用して、すべてのユーザーに異なるCookieを定義できます。すべてのユーザーごとに異なるファイルを作成して、リモートサーバー上でそれぞれ独自のCookieベースのセッションを作成します。

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

または一時的なデータの格納がどこにあるクッキーのデータを参照してください。実行カールのinit魔女のクッキーが一時ファイルとして保存したより

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

+0

多くのユーザーがこのページを使用するとどうなりますか(10千プラス)?それはサーバに大きな負担をかけるのではないでしょうか? – trainoasis

10

まず関数tempnam()を使用して、一時的なクッキーを作成します:

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

これは、Cookieの初期化のページを読み込みます:

curl_setopt ($ch, CURLOPT_COOKIEFILE, $ckfile); 
+0

膨大な数のユーザーが一度にページにアクセスしようとしていて、すでに/ tmpにいくつかのファイルがあるとしたらどうでしょう? PHP docs say: 注意:PHPが指定されたdirパラメータでファイルを作成できない場合は、システムのデフォルトに戻ります。 NTFSでは、これは指定されたdirに65534以上のファイルが含まれている場合にも発生します。 – trainoasis

+0

24時間以上保存した場合、クッキーファイルを削除します。/tmp内のすべてのファイルをチェックするために、$ ckfileのクッキーデータを別々に保管してください。 –

+0

3年後、あなたはまだ私のようなPHP以外の人のための救命マナーです。 stackoverflow答えの負荷を経た後、ここでは順調に説明されています。 –

20

私はWebで遭遇した多くのリソースを結合し、独自の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; 
} 
+0

非常に使いやすいコードです。できます。ありがとうございました。 HTTPステータスコードが必要な場合は、次の構文を使用します。$ header ['http_code']; – jedema

+0

@Doug、私は正規表現 '#Set-Cookie:\\ s +(? [^ =] + = [^;] +)#m'を[ここ](https:// regex101 .com/r/dU3nD8/1)と正規表現エンジンはこの部分を '\\ s +'として説明しています。 '\\'は文字\と文字をマッチします。 's +'文字を文字通り(大文字小文字を区別します)それは正規表現のこの部分で間違いです。 '\ s +'(1つのバックスラッシュのみ)であってはいけませんか? –

+2

@Igor、\\はPHPで文字列を扱うとき(\がエスケープ文字として表示されるため)です(http://php.net/manual/en/language.types.string.php)。結果として、評価された文字列の中に1つのスラッシュに相当する2つのスラッシュが必要になります(RegExの一致に使用されます)。 RegExの観点から正しいですが、スラッシュは1つだけ必要です。 – Doug

2

ここでは、cURLの&クッキーhttp://docstore.mik.ua/orelly/webprog/pcook/ch11_04.htmに関するいくつかの有用な情報を見つけることができます。

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

をそして$cookieパラメータとしてこれを渡します:

あなたはまた、関数のように、このよくやった方法https://github.com/alixaxel/phunction/blob/master/phunction/Net.php#L89を使用することができさえユニークCookieFile名で上記に記載されている

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