2012-10-14 19 views
26

मुझे PHP कर्ल और कुकीज़ प्रमाणीकरण के साथ कुछ समस्या है।PHP कर्ल और कुकीज़

मेरे पास एक फ़ाइल कनेक्टर.php है जो उपयोगकर्ताओं को किसी अन्य सर्वर पर प्रमाणित करती है और वर्तमान उपयोगकर्ता के साथ कुकी लौटाती है।

समस्या यह है कि मैं कर्ल के साथ हजारों उपयोगकर्ताओं को प्रमाणित करना चाहता हूं लेकिन यह एक समय में केवल एक उपयोगकर्ता के लिए कुकीज को प्रमाणित करता है और बचाता है।

  1. उपयोगकर्ता उपयोगकर्ता नाम और पासवर्ड में प्रवेश करती है:

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

    यहाँ प्रमाणीकरण की प्रक्रिया है:

    connector.php के लिए कोड है? Connector.php सेवा = लॉगऑन & user_name = उपयोगकर्ता 32 & user_pass = 123

  2. कनेक्टर.एफ़.पी. सेवा = logosessionInfo यह लॉगऑन सेवा के साथ पहले सहेजी गई कुकीज़ के आधार पर उपयोगकर्ता के बारे में जानकारी देता है।

समस्या यह है कि यह कोड एक उपयोगकर्ता के लिए कुकी में एक फ़ाइल में सहेजता है और एकाधिक उपयोगकर्ता प्रमाणीकरण को संभाल नहीं सकता है।

+2

मैं अद्वितीय PHPSESSID साथ विभिन्न उपयोगकर्ताओं के लिए अलग कुकी फ़ाइलों के निर्माण के साथ मेरी समस्या हल। '$ tmpfname = dirname (__ फ़ाइल __)। '/'। $ _ कुकी ['PHPSESSID']। 'txt';' – Shark

+0

क्या यह एक अच्छा विचार है यदि कई उपयोगकर्ता हैं? – trainoasis

+0

नहीं यदि आपके पास कई उपयोगकर्ता हैं तो यह बुरा है। यह अपाचे सर्वर दुर्घटना का कारण बनता है। मैं इस समस्या को अपाचे प्रॉक्सी के साथ ठीक करता हूं। और मेरे सभी कर्ल कोड हटा दिया। – Shark

उत्तर

0

समाधान जो ऊपर वर्णित हैं, यहां तक ​​कि अद्वितीय CookieFile नाम के साथ, पैमाने पर बहुत सी समस्याएं पैदा कर सकती हैं।

हमें इस समाधान के साथ बहुत सारी प्रमाणीकरण की सेवा करनी थी और हमारे सर्वर उच्च फ़ाइल पढ़ने के कार्यों के कारण नीचे चला गया।

इसका समाधान अपाचे रिवर्स प्रॉक्सी का उपयोग करना था और बिल्कुल कर्ल अनुरोधों को छोड़ना था।

विवरण प्रॉक्सी का उपयोग कैसे करें अपाचे यहां पाया जा सकता है: https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html

22

आप एक कर्ल ऑप्ट के साथ कुकी फ़ाइल निर्दिष्ट कर सकते हैं। आप प्रत्येक उपयोगकर्ता के लिए एक अद्वितीय फ़ाइल का उपयोग कर सकते हैं।

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

मैं इसे त्वरित पकड़ के लिए उपयोग करता हूं। यह यूआरएल और विकल्पों की एक सरणी लेता है।

+0

धन्यवाद, मेरी समस्या हल! – user3236289

1

आप CURLOPT_COOKIEFILE और CURLOPT_COOKIEJAR के साथ प्रत्येक उपयोगकर्ता के लिए अलग-अलग कुकीज़ को परिभाषित कर सकते हैं। प्रत्येक उपयोगकर्ता के लिए अलग-अलग फ़ाइल बनाएं ताकि प्रत्येक व्यक्ति के पास दूरस्थ सर्वर पर स्वयं का कुकी-आधारित सत्र होगा।

+0

इस पृष्ठ का उपयोग कितने उपयोगकर्ताओं द्वारा किया जाता है (10 हजार प्लस)? क्या यह सर्वर पर एक बड़ा भार नहीं है? – trainoasis

10

पहले tempnam का उपयोग कर अस्थायी कुकी बनाने के() फ़ंक्शन:

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

या जाएँ कुकी डेटा जहां अस्थायी आंकड़ों के दुकान है:

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

कर्ल init डायन कुकी पर अमल से एक अस्थायी फ़ाइल के रूप में बचाता है :

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

यह कुकी प्रारंभिक पृष्ठ का पृष्ठ लोड करेगा:

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

क्या होगा यदि बड़ी संख्या में उपयोगकर्ता पृष्ठ को एक बार में एक्सेस करने का प्रयास करते हैं और उदाहरण के लिए आपके पास पहले से ही कुछ फ़ाइलें हैं/tmp? PHP दस्तावेज़ कहते हैं: नोट: यदि PHP निर्दिष्ट डीआईआर पैरामीटर में कोई फ़ाइल नहीं बना सकता है, तो यह सिस्टम डिफ़ॉल्ट पर वापस आ जाता है। एनटीएफएस पर यह भी होता है यदि निर्दिष्ट डीआईआर में 65534 से अधिक फाइलें हैं। – trainoasis

+0

24h से अधिक समय के लिए संग्रहीत कुकी फ़ाइलों को निकालें।/Cmp के अंदर सभी फ़ाइलों की जांच के लिए $ ckfile के लिए एक कुकी डेटा स्टोर करें। –

+0

3 वर्षों के बाद, आप अभी भी मेरे जैसे गैर-PHP व्यक्तियों के लिए एक जीवन बचतकर्ता मारिन हैं। स्टैक ओवरफ्लो उत्तरों के लोड के माध्यम से जाने के बाद, यहां एक अच्छी तरह से व्यवस्थित तरीके से समझाया गया है। –

20

इसी तरह की समस्या के साथ काम करने में मैंने वेब पर बहुत सारे संसाधनों को जोड़ने के बाद निम्नलिखित कार्य किया, और अपनी कुकी हैंडलिंग जोड़ दी। उम्मीद है कि यह किसी और के लिए उपयोगी है।

 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 स्टेटस कोड इस वाक्यविन्यास का उपयोग करें: $ हेडर ['http_code']; – jedema

+0

@Doug, मैंने रेगेक्स '# सेट-कुकी: \\ s + (? [^ =] + = [^;] +) आपके कोड का # एम' [https] में देखा है (https: // regex101 .com/r/dU3nD8/1) और रेगेक्स इंजन इस भाग को \\ s + 'के रूप में बताता है:' \\ 'अक्षर से मेल खाता है \ सचमुच ' s + 'अक्षर के अक्षर से मेल खाता है (केस संवेदनशील) - नहीं है यह regex के इस हिस्से में एक गलती है, यह '\ s +' (केवल एक बैकस्लैश) नहीं होना चाहिए? –

+2

@ इगोर, \\ इसलिए है क्योंकि PHP में तारों से निपटने पर [\ को एक भागने वाले चरित्र के रूप में देखा जाता है] (http://php.net/manual/en/language.types.string.php)। नतीजतन आपको मूल्यांकन की गई स्ट्रिंग में बराबर एक स्लैश के लिए दो स्लेश की आवश्यकता होती है (जिसे फिर RegEx मैच के लिए उपयोग किया जाएगा)। आप RegEx दृष्टिकोण से सही हैं I केवल एक स्लैश चाहते हैं। – Doug

2

यहाँ आप cURL & कुकीज़ http://docstore.mik.ua/orelly/webprog/pcook/ch11_04.htm बारे में कुछ उपयोगी जानकारी पा सकते हैं।

तुम भी एक समारोह की तरह इस अच्छी तरह से किया विधि 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; 
} 

और $cookie पैरामीटर के रूप में यह पारित:

$cookie_jar = tempnam('/tmp','cookie'); 
संबंधित मुद्दे