PHP cURL模拟登录HTTPS无验证码的WebServices
2018-01-05 18:08
309 查看
近期使用PHP的SoapClient调用.net的WebServices始终行不通,然而又没有对方技术人员支持的情况,尝试着 WSDL 模式和 non-WSDL 模式都无果,在 new SoapClient时直接会报错,在网上找了一个服务是可以正常调用的,说明运行环境正常:
对方给的 WebServices URL直接访问的是跳登录页了,登录之后访问 WebServices 是正常的,则先使用cURL的模拟登录然后携带登录返回的cookie请求WebServices,请求的参数中有一个是将XML转为
base64Binary 传输。
传输的编码 Content-Type:application/x-www-form-urlencoded
所以在这里POST的参数为字符串,如 param1=value1¶m2=value2
如果使用数组,则 Content-Type 会变为表单上传的类型。
以下用代码和注释说明:
$wsdlUrl = "http://www.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx?wsdl"; $client = new SoapClient($wsdlUrl, $array('encoding' => 'utf-8')); //$client = new SoapClient(null, array('encoding' => 'utf-8', 'uri'=> $uri, 'location' => $wsdlUrl, 'trace' => true));但我这边调用的服务是 HTTPS 带登录验证的服务,连实例化时都过不去,于是改用POST方式尝试着。
对方给的 WebServices URL直接访问的是跳登录页了,登录之后访问 WebServices 是正常的,则先使用cURL的模拟登录然后携带登录返回的cookie请求WebServices,请求的参数中有一个是将XML转为
base64Binary 传输。
传输的编码 Content-Type:application/x-www-form-urlencoded
所以在这里POST的参数为字符串,如 param1=value1¶m2=value2
如果使用数组,则 Content-Type 会变为表单上传的类型。
以下用代码和注释说明:
<?php /** * CurlSoap * * 参考: * https://github.com/Zjmainstay/php-curl * https://segmentfault.com/a/1190000003808546 */ class CurlSoap { /** * @var string 服务地址,测试 https://localhost/Service.asmx/HelloWorld */ public $wsdl = 'https://localhost/Service.asmx/VisitorData'; /** * @var string 验证地址 */ public $checkUrl = 'https://localhost/login.form'; /** * @var string 如果失败尝试次数 */ protected $testTry = 3; protected $isCheck; protected $cookieArr; private $supplyCode; private $username; private $password; public function __construct() { $this->cookieArr = array(array(),array()); $this->supplyCode = ''; $this->username = 'username'; $this->password = 'password'; //先检测是否已登录 if(!$this->isCheck){ $this->checking(); } } /** * 请求服务 * */ public function postdata() { try { //将XML转为 base64Binary , xml模板由服务方提供 $xmlStr = $this->getXml(); //先将XML转为 base64 string $baseEncode = base64_encode($xmlStr); //再转为 byte 数组 $base64BinaryArr = $this->getBytes($baseEncode); //将byte拼接为POST 的字符串参数时, 因对方不需要 &bytes[]= 可以接受到所有参数 $bytesParam = implode('&bytes=', $base64BinaryArr); $param = array( 'url' => $this->wsdl, 'cookie' => $this->cookieArr[1], //携带登录后的cookie访问 'header' => array( 'Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Content-Type:application/x-www-form-urlencoded' ), 'data' => 'supplyCode='. $this->supplyCode .'&bytes='. $bytesParam ); $res = $this->curlPost($param); if($res){ $xmlObj = simplexml_load_string($res); // print_r($xmlObj); exit; if(strtoupper($xmlObj->CODE) == 'S'){ return true; } } } catch (Exception $e) { // libxml_get_last_error(); } return false; } protected function getXml() { $xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <msg ver="1.0"> <meta> <field name="SOURCE" val="" /> </meta> <head> <field name="SEND" val="'. date('Y-m-d H:i:s') .'" type="System.DateTime" /> </head> <body> '; $xmlTpl = '<vo name="VISITOR"> <field name="ID" val="%d" type="System.Int32" /> <field name="NAME" val="%s" type="System.String" /> </vo> '; $data = array( array('id' => 1, 'user_name' => 'test'), ); foreach ($data as $val){ $xml .= sprintf($xmlTpl, $val['id'], trim($val['user_name']) ); } $xml .= '</body> </msg>'; //格式化xml $xml = preg_replace('/\s{2,}/', '', $xml); $xml = str_replace('><', ">\n<", $xml); return $xml; } /** * 登录 * */ private function checking() { $param = array( 'url' => $this->checkUrl, 'nobody' => 1, 'header' => array( 'Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Content-Type:application/x-www-form-urlencoded' ), 'data' => 'username='. $this->username .'&password='. $this->password ); //多次尝试登陆 for($i=0; $i < $this->testTry; $i++){ $resData = $this->curlPost($param); if(preg_match('@HTTP/1.1\s*200\s*OK@i', $resData)){ $this->isCheck = true; //登录成功 保存Cookie preg_match_all('|Set-Cookie: (.*);|U', $resData, $this->cookieArr); break; } } } protected function curlPost($param) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $param['url']); // 对认证证书来源的检查, false 表示阻止对证书的合法性的检查 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 从证书中检查SSL加密算法是否存在 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//关闭直接输出 curl_setopt($ch,CURLOPT_POST,1);//使用post提交数据 curl_setopt($ch,CURLOPT_POSTFIELDS, $param['data']);//设置 post提交的数据, 区别数组与字符串 curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36');//设置用户代理 //Boolean if(isset($param['nobody'])){ //curl_setopt($ch, CURLOPT_NOBODY, 1); //不需要HTML实体 curl_setopt($ch, CURLOPT_HEADER, 1); //是否头文件信息 } /** * Array * array('Content-Type:application/x-www-form-urlencoded', 'Referer:https://localhost') */ if(isset($param['header'])){ curl_setopt($ch,CURLOPT_HTTPHEADER, $param['header']);//设置头信息 } /** * 携带Cookie访问 * array(0=>'SID=abcde', 1=>'ppid=123') */ if(isset($param['cookie'])){ $cookies = implode('; ', $param['cookie']); curl_setopt($ch, CURLOPT_COOKIE, $cookies); } // curl_setopt($ch, CURLOPT_SSLVERSION, 3); //设定SSL版本 //保存Cookie //$cookie_file = '/tmp/rqwebservices.cookie'; //tempnam('/tmp','cookie'); // curl_setopt($ch,CURLOPT_COOKIEJAR,$cookie_file);//设置cookie的保存目录 $data = curl_exec($ch); if (curl_errno($ch)) { return false; } curl_close($ch); return $data; } /** * 将字节数组转化为String类型的数据 * @param array $bytes * @return string */ public function toStr($bytes) { $str = ''; foreach($bytes as $ch) { $str .= chr($ch); } return $str; } /** * 转换一个String字符串为byte数组 * @param string $string * @return array */ public function getBytes($string) { $bytes = array(); for($i = 0; $i < strlen($string); $i++){ $bytes[] = ord($string[$i]); } return $bytes; } }
相关文章推荐
- PHP curl模拟登录带验证码的网站
- PHP curl模拟登录带验证码的网站
- 在Python中用Request库模拟登录(二):博客园(简单加密,无验证码)
- Python3.4 模拟登录校园网 技巧和大坑记录 无验证码
- [置顶] Android模拟登录教务处(带验证码)
- VC显示网页验证码、模拟CSDN网页登录
- 模拟http或https请求,实现ssl下的bugzilla登录、新增BUG,保持会话以及处理token
- PHP CURL获取cookies模拟登录的方法
- Python爬虫模拟登录带验证码网站
- PHP CURL 模拟登录 SINA 微博
- 使用PHP-curl获取验证码并模拟登录教务系统
- python爬虫实战(四)--------豆瓣网的模拟登录(模拟登录和验证码的处理----scrapy)
- C++ 纯socket 模拟登录37.com【过验证码】
- VC显示网页验证码、模拟CSDN网页登录
- HttpClient 模拟登录豆瓣网(有验证码)
- Python爬虫模拟登录带验证码网站
- PHP使用CURL实现对带有验证码的网站进行模拟登录的方法
- C++模拟Http/Https POST登录web站点
- C# 利用 HttpWebRequest 和 HttpWebResponse 模拟登录有验证码的网站