详细内容见程序注释.
<?php /** * 功能: 模拟新浪微博登陆 * 用途: 模拟用户登陆, 以便进行后续操作, 比如自动化的控制自己的新浪app刷新某些数据 * 注意事项: * 1. 需要安装nodejs * 2. 需要下载新浪的加密js文件, 请到新浪登陆页查看网络请求自己下载最新版本(我当时用的: http://js.t.sinajs.cn/t35/miniblog/static/js/sso.js?version=e482ef2bbdaa8bc2) * 3. 对新浪加密js文件进行修改, 以便让nodejs可以运行它 * 1) 在文件前面增加下面内容 var window = { location : { hash : '', host : 'weibo.com', hostname : 'weibo.com', href : 'http://weibo.com/', pathname : '/', port : '', protocol : 'http:', search : '' }, navigator : { appCodeName : 'Mozilla', appName : 'Netscape', appVersion : '5.0 (Macintosh)', buildID : '20120713134347', cookieEnabled : true, doNotTrack : 'unspecified', language : 'en-US' } }; var location = window.location; var navigator = window.navigator; * 2) 在文件后面增加下面内容 var argv = process.argv.splice(2); var pubkey = argv[0], servertime = argv[1], nonce = argv[2], password = argv[3]; var RSAKey = new sinaSSOEncoder.RSAKey(); RSAKey.setPublic(pubkey, '10001'); password = RSAKey.encrypt([servertime, nonce].join("\t") + "\n" + password); console.log(password); process.exit(); * 4. 修改encode_password函数中的nodejs程序路径和修改后的新浪js文件路径 * 5. 修改用户名密码 * author: selfimpr * blog: http://blog.csdn.net/lgg201 * mail: [email protected] */ define('REQUEST_METHOD_GET', 'GET'); define('REQUEST_METHOD_POST', 'POST'); define('REQUEST_METHOD_HEAD', 'HEAD'); define('COOKIE_FILE', '/tmp/sina.login.cookie'); function curl_switch_method($curl, $method) { switch ( $method) { case REQUEST_METHOD_POST: curl_setopt($curl, CURLOPT_POST, TRUE); break; case REQUEST_METHOD_HEAD: curl_setopt($curl, CURLOPT_NOBODY, TRUE); break; case REQUEST_METHOD_GET: default: curl_setopt($curl, CURLOPT_HTTPGET, TRUE); break; } } function curl_set_headers($curl, $headers) { if ( empty($headers) ) return ; if ( is_string($headers) ) $headers = explode("\r\n", $headers); #类型修复 foreach ( $headers as &$header ) if ( is_array($header) ) $header = sprintf('%s: %s', $header[0], $header[1]); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); } function curl_set_datas($curl, $datas) { if ( empty($datas) ) return ; curl_setopt($curl, CURLOPT_POSTFIELDS, $datas); } function curl_request($url, $method = REQUEST_METHOD_GET, $datas = NULL, $headers = NULL) { static $curl; if ( !$curl ) $curl = curl_init(); curl_switch_method($curl, $method); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE); curl_setopt($curl, CURLOPT_AUTOREFERER, TRUE); curl_setopt($curl, CURLOPT_COOKIEJAR, COOKIE_FILE); curl_setopt($curl, CURLOPT_COOKIESESSION, TRUE); if ( $datas ) curl_set_datas($curl, $datas); if ( $headers) curl_set_headers($curl, $headers); $response = curl_exec($curl); if ( $errno = curl_errno($curl) ) { error_log(sprintf("%10d\t%s\n", $errno, curl_error($curl)), 3, 'php://stderr'); return FALSE; } return $response; } function get_js_timestamp() { return time() * 1000 + rand(0, 999); } function http_build_query_no_encode($datas) { $r = array(); foreach ( $datas as $k => $v ) $r[] = $k . '=' . $v; return implode('&', $r); } function makeUrl($url, $info, $encode = TRUE) { if ( !is_array($info) || empty($info) ) return $url; $components = parse_url($url); if ( array_key_exists('query', $components) ) $query = parse_str($components['query']); else $query = array(); if ( is_string($info) ) $info = parse_str($info); $query = array_merge($query, $info); $query = $encode ? http_build_query($query) : http_build_query_no_encode($query); $components['scheme'] = array_key_exists('scheme', $components) ? $components['scheme'] . '://' : ''; $components['user'] = array_key_exists('user', $components) ? $components['user'] . ':' . $components[HTTP_URL_PASS] . '@' : ''; $components['host'] = array_key_exists('host', $components) ? $components['host'] : ''; $components['port'] = array_key_exists('port', $components) ? ':' . $components['port'] : ''; $components['path'] = array_key_exists('path', $components) ? '/' . ltrim($components['path'], '/') : ''; $components['query'] = $query ? '?' . $query : ''; $components['fragment'] = array_key_exists('fragment', $components) ? '#' . $components['fragment'] : ''; return sprintf('%s%s%s%s%s%s%s', $components['scheme'], $components['user'], $components['host'], $components['port'], $components['path'], $components['query'], $components['fragment']); } function encode_username($username) { return base64_encode(urlencode($username)); } function encode_password($pub_key, $password, $servertime, $nonce) { #这里是要用nodejs执行新浪的js文件 $response = `/usr/local/node.js-0.8.8/bin/node sina.js "$pub_key" "$servertime" "$nonce" "$password"`; return substr($response, 0, strlen($response) - 1); } function main_page() { return curl_request('weibo.com'); } function prepare_login_info() { $time = get_js_timestamp(); $url = makeUrl('http://login.sina.com.cn/sso/prelogin.php', array( 'entry' => 'sso', 'callback' => 'sinaSSOController.preloginCallBack', 'su' => encode_username('undefined'), 'rsakt' => 'mod', 'client' => 'ssologin.js(v1.4.2)', '_' => $time, ), FALSE); $response = curl_request($url); $length = strlen($response); $left = 0; $right = $length - 1; while ( $left < $length ) if ( $response[$left] == '{' ) break; else $left ++; while ( $right > 0 ) if ( $response[$right] == '}' ) break; else $right --; $response = substr($response, $left, $right - $left + 1); return array_merge(json_decode($response, TRUE), array( 'preloginTime' => max(get_js_timestamp() - $time, 100), )); } function login($info, $username, $password) { $feedbackurl = makeUrl('http://weibo.com/ajaxlogin.php', array( 'framelogin' => 1, 'callback' => 'parent.sinaSSOController.feedBackUrlCallBack', )); $datas = array( 'encoding' => 'UTF-8', 'entry' => 'weibo', 'from' => '', 'gateway' => 1, 'nonce' => $info['nonce'], 'prelt' => $info['preloginTime'], 'pwencode' => 'rsa2', 'returntype' => 'META', 'rsakv' => $info['rsakv'], 'savestate' => 7, 'servertime' => $info['servertime'], 'service' => 'miniblog', 'sp' => encode_password($info['pubkey'], $password, $info['servertime'], $info['nonce']), 'ssosimplelogin' => 1, 'su' => encode_username($username), 'url' => $feedbackurl, 'useticket' => 1, 'vsnf' => 1, ); $url = makeUrl('http://login.sina.com.cn/sso/login.php', array( 'client' => 'ssologin.js(v1.4.2)', ), FALSE); $response = curl_request($url, REQUEST_METHOD_POST, $datas); $sign = 'location.replace(\''; $response = substr($response, strpos($response, $sign) + strlen($sign)); $location = substr($response, 0, strpos($response, '\'')); $response = curl_request($location); $length = strlen($response); $left = 0; $right = $length - 1; while ( $left < $length ) if ( $response[$left] == '{' ) break; else $left ++; while ( $right > 0 ) if ( $response[$right] == '}' ) break; else $right --; $response = substr($response, $left, $right - $left + 1); return json_decode($response, true); } $info = prepare_login_info(); $info = login($info, '用户名', '密码'); echo curl_request('http://weibo.com/u/' . $info['userinfo']['uniqueid'] . $info['userinfo']['userdomain']);