我正在尝试使用 php curl 从外部网页获取登录令牌 但我收到的登录令牌与实际的不同。
有人可以告诉我我错过了什么吗?
$ch = curl_init();
url_setopt($ch, CURLOPT_URL, "https://grprek.jeddahknowledgeschool.com/login/index.php");
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, "");
$answer = curl_exec($ch);
echo $answer;
if (curl_error($ch)) {
echo curl_error($ch);
}
?>
<form action="<?php echo $virtualLink; ?>" method="post" target="_new" id="login" >
<input name="logintoken" type="hidden" value="<?php echo $vlLoginToken;?>" />
<input style="background-color: transparent;" id="username" name="username" type="hidden" value="<?php echo $username;?>" >
<input id="password" name="password" type="hidden" value="<?php echo $vlPassword;?>">
<input style=" width:100px; height:100px; margin-right:auto; margin-left:auto; display:block; border:none; background-color: transparent;"
src=""
type="image"
alt="turnitin"
title="turnitin">
</form>
</td>
使用下面相当基本且可重用的函数来发出curl 请求,您最初会执行
GET
请求来开始会话。初始 GET
请求用于发现和存储所使用的 cookie,并解析 HTML 以从表单中查找 logintoken
。
您使用
DOMDocument/DOMXpath
处理 HTML 并查找令牌。然后,发现的令牌将用于创建 POST
请求 - 即:登录。
function curl( $url=null, $options=null ){
/*
Download a copy of CACERT.pem from
https://curl.haxx.se/docs/caextract.html
and edit path below
*/
$cacert='c:/wwwroot/cacert.pem';
$curl=curl_init();
if( parse_url( $url, PHP_URL_SCHEME )=='https' ){
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, true );
curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, 2 );
curl_setopt( $curl, CURLOPT_CAINFO, $cacert );
}
curl_setopt( $curl, CURLOPT_URL, trim( $url ) );
curl_setopt( $curl, CURLOPT_AUTOREFERER, true );
curl_setopt( $curl, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $curl, CURLOPT_FAILONERROR, true );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $curl, CURLOPT_CONNECTTIMEOUT, 20 );
curl_setopt( $curl, CURLOPT_TIMEOUT, 60 );
curl_setopt( $curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' );
curl_setopt( $curl, CURLOPT_MAXREDIRS, 10 );
curl_setopt( $curl, CURLOPT_ENCODING, '' );
# add runtime options
if( isset( $options ) && is_array( $options ) ){
foreach( $options as $param => $value ) {
curl_setopt( $curl, $param, $value );
}
}
$res=(object)array(
'response' => curl_exec( $curl ),
'status' => curl_getinfo( $curl, CURLINFO_RESPONSE_CODE )
);
curl_close( $curl );
return $res;
}
# create a temporary file to hold cookie data used by subsequent curl requests.
$cookiejar=tempnam( sys_get_temp_dir(), '_cookiejar_' );
# Target endpoint - initially loaded using GET to find cookies and parse the HTML to find the logintoken
$url='https://grprek.jeddahknowledgeschool.com/login/index.php';
# options used to make GET request.
# Cookie data will be saved to $cookiejar when curl_close() is called.
$options=array(
CURLOPT_COOKIESESSION => true,
CURLOPT_COOKIEJAR => $cookiejar
);
# make the request and proceed if it succeeds
$res=curl( $url, $options );
if( $res->status==200 ){
# The POST parameters to send.
# "logintoken" will be added below!
$args=array(
'username' => 'xxx',
'password' => 'xxx'
);
# Load the HTML to find logintoken
libxml_use_internal_errors( true );
$dom = new DOMDocument;
$dom->loadHTML( $res->response );
libxml_clear_errors();
#create an XPath to query the DOM and find INPUT elements within the form
$xp=new DOMXPath( $dom );
$expr='//form[ @class="login-form" ]//input';
$col=$xp->query( $expr );
# If the XPath succeeded, grab the name/value and assign as login arguments
if( $col && $col->length > 0 ){
# iterate through discovered inputs, add name/value to args array.
# do not overwrite known values of username/password ( if known of course )
# This is where the "logintoken" is added!
foreach( $col as $node ){
if( !array_key_exists( $node->getAttribute('name'), $args ) ){
$args[ $node->getAttribute('name') ]=$node->getAttribute('value');
}
}
# create the curl options for the POST request.
# use the cookie but do not start new cookie session.
$options=array(
CURLOPT_COOKIESESSION => false,
CURLOPT_COOKIEFILE => $cookiejar,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query( $args )
);
# make the curl request...
$res=curl( $url, $options );
if( $res->status==200 ){
# Can progress no further or identify any errors beyond this point due to no valid credentials.
# so simply print out HTML response that shows "Invalid login, please try again"
# If the login succeeds then there will be different displayed HTML presumably.
printf(
'<pre>%s</pre>',
print_r( $res->response, true )
);
#interested in seeing cookie?
printf('<pre>%s</pre>',file_get_contents($cookiejar));
# after all processing... erase cookie?
unlink( $cookiejar );
}else{
printf( 'POST request failed with code: %s', $res->status );
}
}
}else{
printf( 'GET request failed with code: %s', $res->status );
}