2017-10-12 121 views
1

我試圖登錄到網站,但收到「身份驗證失敗」錯誤,就好像我錯誤地使用用戶名或密碼。傳遞的參數是正確的,包括用戶名和密碼,因爲我在Java中開發了相同的代碼並且它可以工作。發送字段時我犯了錯誤嗎?PHP:發送http post請求但「身份驗證失敗」

$cookies = array(); 
foreach ($http_response_header as $hdr) { 
    if (preg_match('/^Set-Cookie:\s*([^;]+)/', $hdr, $matches)) { 
     parse_str($matches[1], $tmp); 
     $cookies += $tmp; 
    } 
} 
$cookie= reset($cookies); 

$request = array(
    'http' => array(
     'method' => 'POST', 
     'timeout' => 0, 
     'header'=> "Accept-language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3\r\n" . 
      "Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n" . 
      "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6\r\n" . 
      "Cookie: ASP.NET_SessionId=".$cookie."\r\n", 
     'content' => http_build_query(array(
      '__LASTFOCUS' => '', 
      '__EVENTTARGET' => '', 
      '__EVENTARGUMENT' => '', 
      '__VIEWSTATE' => $viewstate, 
      '__VIEWSTATEGENERATOR' => $viewstategenerator, 
      'ctl00$hwsid' => $hwsid, 
      'ctl00$PageSessionId' => $pagesessionid, 
      'ctl00$DefaultUrl' => $defaulturl, 
      'ctl00$GenericErrorUrl' => $genericerrorurl, 
      'ctl00$PopupElement' => '', 
      'ctl00$PollingTimeoutSecs' => $pollingtimeoutsecs, 
      'ctl00$bodyContent$txtUser' => $user, 
      'ctl00$bodyContent$txtPassword' => $password, 
      '__CALLBACKID' => '__Page', 
      '__CALLBACKPARAM' => '"hwsid="'.$hwsid.'"&PageSessionId="'.$pagesessionid.'"&DefaultUrl="'.$defaulturl.'"&GenericErrorUrl="'.$genericerrorurl.'"&PopupElement="'.'"&PollingTimeoutSecs="'.$pollingtimeoutsecs.'"&txtUser="'.$user.'"&txtPassword="'.$password, 
      '__EVENTVALIDATION' => $eventvalidation, 
      'ctl00$bodyContent$btnLogin' => 'Conferma' 

     )), 
    ) 
); 

$context = stream_context_create($request); 
$res= file_get_contents($url, false, $context); 
echo htmlentities($res); 

用於Java的工作代碼如下:

cookies = initialResponse.cookies(); 

       initialResponse = Jsoup.connect(url+"Default.aspx") 
        .data("__LASTFOCUS", "") 
        .data("__EVENTTARGET", "") 
        .data("__EVENTARGUMENT", "") 
        .data("__VIEWSTATE", executionVal) 
        .data("__VIEWSTATEGENERATOR", vv1) 
        .data("ctl00$hwsid", a11) 
        .data("ctl00$PageSessionId", a22) 
        .data("ctl00$DefaultUrl", a33) 
        .data("ctl00$GenericErrorUrl", a44) 
        .data("ctl00$PopupElement", "") 
        .data("ctl00$PollingTimeoutSecs", a66) 
        .data("ctl00$bodyContent$txtUser", user) 
        .data("ctl00$bodyContent$txtPassword", pass) 
        .data("__CALLBACKID", "__Page") 
        .data("__CALLBACKPARAM", "hwsid="+a11+"&PageSessionId="+a22+"&DefaultUrl="+a33+"&GenericErrorUrl="+a44+"&PopupElement="+"&PollingTimeoutSecs="+a66+"&txtUser="+user+"&txtPassword="+pass) 
        .data("__EVENTVALIDATION", ltVal) 
        .data("ctl00$bodyContent$btnLogin", "Conferma") 
        .cookies(cookies) 
        .userAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36") 
        .method(Method.POST) 
        .timeout(0) 
        .execute(); 
      }catch(UnknownHostException e){ 
       JOptionPane.showMessageDialog(null, "No", "Turni", JOptionPane.ERROR_MESSAGE); 
       System.exit(0); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

      cookies.putAll(initialResponse.cookies()); 

      Document doc = null; 
      try { 
       doc = Jsoup.connect(u) 
        .cookies(cookies) 
        .get(); 

      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
+0

看看最終的URL,cookies和POST正文可能有幫助;然後將它們與工作版本進行比較。 – miken32

+0

我想我已經理解了,實際上,當我訪問網站時第一個cookie被生成(ASP_NET_SessionId = wpxfk3msbyghw5nlo2wlxer),一旦您發送請求信息與該cookie,該網站發佈另一個能夠訪問,我認爲你有(SSOAuth = DF1D63B311125E1C34689C7D16B4BE4D798E718C1A037B189A2284797B7FFB) 加那麼到後最終請求,餅乾將添加兩個cookie「ASP_NET_SessionId = wpxfk3msbyghw5nlo2wlxer; SSOAuth = DF1D63B311125E1C34689C7D16B4BE4D798E718C1A037B189A2284797B7FFB」,但我怎麼在代碼中得到,並添加第二個cookie? – Enzo

回答

0

我懷疑你濫用reset()。它返回第一個數組元素的值。所以如果你收到多個cookie,你可能會遇到問題。如果你正在尋找一個特定的Cookie,你可以做這樣的事情:

// here's what we're looking for 
$target = "ASP.NET_SessionId"; 

// filter the array 
$cookies = array_filter(
    $http_response_header, 
    function($v) use ($target) {return strpos($v, "Set-Cookie: $target=") === 0;} 
); 

if (!empty($cookies)) { 
    // here we know we only have a single entry in the array 
    $cookie = reset($cookies); 
    $cookie = preg_replace("/.*=([^;]*)/", "$1", $cookie); 
} else { 
    // no cookies received! 
    $cookie = ""; 
} 

真的,這是一個複雜得多比它需要的是雖然。最簡單的做法是取出所有的cookies並將它們發回第二個請求:

$cookies = array_filter(
    $http_response_header, 
    function($v) {return strpos($v, "Set-Cookie:") === 0;} 
); 
$headers = [ 
    "Accept-language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3", 
    "Content-Type: application/x-www-form-urlencoded; charset=utf-8", 
    "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6", 
]; 
foreach ($cookies as $cookie) { 
    $headers[] = preg_replace("/^Set-/", "", $cookie); 
} 

$request = [ 
    "http" => [ 
     "method" => "POST", 
     "timeout" => 0, 
     "header"=> $headers, 
     "content" => "..." 
]; 
+0

更容易的是使用curl函數,它會自動處理cookie。 – miken32

+0

正如我以前寫過的,當我訪問網站時會生成第一個cookie(ASP_NET_SessionId = wpxfk3msbyghw5nlo2wlxer),一旦您發送了包含該cookie的請求帖子,該站點就會發出另一個可以訪問的cookie,而且我認爲您有添加(SSOAuth = DF1D63B311125E1C34689C7D16B4BE4D798E718C1A037B189A2 284797B7FFB),所以到後最終請求,餅乾將添加兩個cookie「ASP_NET_SessionId = wpxfk3msbyghw5nlo2wlxer; SSOAuth = DF1D63B311125E1C34689C7D16B4BE4D798E718C1A037B189A22 84797B7FFB」,但我如何才能在代碼並添加第二個cookie? – Enzo

+0

上面的第二個代碼塊從響應中獲取所有cookie並將它們放入您的請求中。 – miken32