示例代理:http://ce.monihe.com/proxy.php
<?php /** * 如意册 AJAX跨域请求【代理】功能示范 * 注意: * !此代理$alow_domains指定允许代理的域名列表,请添加您的域名或关闭此安全设置; * 此代理支持files($_FILES)的代理上传提交,但需要PHP5.6及以上版本;; * 但不支持header头的代理提交; * 使用代理调试、测试目标请求,会增加更多的错误因素(如:header、cookie、referer、编码、跨域 等); * 此代理程序仅供参考、示范; * 推荐尽量使用直接跨域请求的方案; * @author libowen * @for 如意册 http://ruyice.com/ * @date 2017-11 */ define('APP_DEBUG', true); if(APP_DEBUG){ // 注意:跨域请求必须的设置(允许从指定域名发来的请求) $origin = !empty($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : (!empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''); if($origin){ $ruyice_domain = 'ruyice.com'; // 只允许从指定域名发来的请求 if($_SERVER['HTTP_HOST'] != $ruyice_domain){ $parseUrl = parse_url($origin); if($ruyice_domain === $parseUrl['host']){ // 必须包括协议scheme $allow_origin = $parseUrl['scheme'] . '://' . $parseUrl['host']; // 允许指定域名发来的访问请求,即固定限制为客户端网址 header("Access-Control-Allow-Origin: " . $allow_origin); header("Access-Control-Allow-Methods: POST,GET,PUT,OPTIONS,DELETE"); // 是否允许请求带有验证信息,如cookie header("Access-Control-Allow-Credentials: true"); if('OPTIONS' === strtoupper($_SERVER['REQUEST_METHOD'])){ // 支持的请求header字段名 header("Access-Control-Allow-Headers: DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, SessionID,ASPSESSIONID,ASP.NET_SessionId,JsessionId,PHPSESSID,Authorization,access-token,RuYiCe-DIY-Allow"); // 允许自定义的头部,以逗号隔开,不含下划线,大小写不敏感(RuYiCe-DIY-Allow 可更换为需要ajax发送的header字段名,多个则英文逗号分隔,否则浏览器会屏蔽掉返回的结果) header("HTTP/1.1 204 Accepted"); exit; } /* // 开放式开发、测试时,可考虑加个header安全验证 $access_key = 'access-token'; // 自定义(但要在请求的header中包含,且服务器端Access-Control-Allow-Headers包含) $access_password = 'access-token-value'; $access_key = strtoupper(str_replace('-', '_', $access_key)); if($access_password !== $_SERVER['HTTP_' . $access_key]){ header("Content-type: text/html; charset=utf-8"); echo json_encode([ 'code' => 0, 'msg' => 'access-token not right! header头的安全验证错误!', 'data' => [] ]); exit; } */ // 设置为ajax请求方式 if($_SERVER['HTTP_HOST'] != $ruyice_domain){ $_SERVER['HTTP_' . 'X_REQUESTED_WITH'] = 'XMLHttpRequest'; } } else { // 非指定域名发来的,则忽略上面的设置 } } } } // header("content-Type: text/html; charset=UTF-8"); $is_post = false; if (!empty($_POST)) { $is_post = true; } $url = (!empty($_GET['source_url']) ? urldecode($_GET['source_url']) : (!empty($_GET['url']) ? urldecode($_GET['url']) : '')); if (empty($url)) { if ($is_post) { $url = (!empty($_POST['source_url']) ? $_POST['source_url'] : (!empty($_POST['url']) ? $_POST['url'] : '')); } } if (empty($url)) { $return = [ 'error_code' => 10001, 'msg' => '未指定url' ]; exit_return($return); } // 指定允许的域名,非指定域名则中断并提示 $alow_domains = ['ce.monihe.com', 'ce.dev.monihe.com', 'yourdomain', 'suggest.taobao.com', 'www.kuaidi100.com', 'baike.baidu.com', 'api.map.baidu.com', 'm.weather.com.cn', 'php.weather.sina.com.cn', 'qzone-music.qq.com', 'v5.pc.duomi.com', 'cgi.music.soso.com', 'v.youku.com', 'cache.video.iqiyi.com', 'api.tudou.com', 'www.tudou.com', 'gc.ditu.aliyun.com', 'www.telize.com', 'ditu.amap.com', 'int.dpool.sina.com.cn', 'ip.taobao.com', 'tcc.taobao.com', 'virtual.paipai.com', 'www.baifubao.com', 'cz.115.com', 'www.youdao.com', 'api.showji.com', 'dict.qq.com', 'r.qzone.qq.com', 'ajax.googleapis.com']; $url_host = parse_url($url)['host']; if(!in_array($url_host, $alow_domains)){ $return = [ 'error_code' => 10002, 'msg' => '指定被代理的url不在允许范围!请把 '.$url_host.' 添加到代理程序的$alow_domains数组', 'source_url' => parse_url($url), 'allow_domains' => isset($alow_domains)?$alow_domains:null ]; exit_return($return); } if (!$is_post) { if (strpos($url, '?') === false) { $url .= '?'; } $get_data = $_GET; if($get_data){ unset($get_data['source_url']); // unset($get_data['url']); $url .= '&' . http_build_query($get_data); } } // 提交登录表单请求 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_TIMEOUT, 5); // 设置curl执行超时时间最大是多少 // 伪造网页来源地址 //curl_setopt($ch, CURLOPT_REFERER, "http://ruyice.com"); $headers = [ 'X-Requested-With: XMLHttpRequest' // header头设置此请求为ajax请求 ]; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // 获取的内容不直接输出,而作为变量 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); if ($is_post) { $post_data = $_POST; curl_setopt($ch, CURLOPT_POST, true); if(empty($_FILES)) { // 无文件上传提交 curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data)); } else { // 含文件上传提交 // header("content-Type: text/html; charset=UTF-8"); // $return = [ // 'error_code' => 10003, // 'msg' => '此代理不支持文件上传提交!', // 'source_url' => parse_url($url), // '$_POST' => $_POST, // '$_FILES' => $_FILES // ]; // exit_return($return); // 限制文件数量和大小 file_limit=5,max_size=512000 $is_error = 0; $file_limit = 5; $max_size = 512000; $file_count = 0; $files_data = []; foreach($_FILES as $key => $value){ if(is_array($value['tmp_name'])){ $temp_count = count($value['tmp_name']); for($i=0; $i<$temp_count; $i++){ $file_count++; if($value['error'][$i] > 0){ $is_error = 1; break; } if($value['size'][$i] > $max_size){ $is_error = 2; break; } // PHP版本5.6及以上,curl文件上传必须使用CurlFile对象 $files_data[$key.'['.$i.']'] = new \CURLFile(realpath($value['tmp_name'][$i]), $value['type'][$i], $value['name'][$i]); } } else { $file_count++; if($value['error'] > 0){ $is_error = 1; break; } if($value['size'] > $max_size){ $is_error = 2; break; } // PHP版本5.6及以上,curl文件上传必须使用CurlFile对象 $files_data[$key] = new \CURLFile(realpath($value['tmp_name']), $value['type'], $value['name']); } if($file_count > $file_limit){ $return = [ 'error_code' => 10004, 'msg' => '已超过代理程序允许上传文件数量:' . $file_limit, '$_FILES' => $_FILES ]; exit_return($return); } if($is_error === 1){ $return = [ 'error_code' => 10005, 'msg' => '提交到代理程序的文件有错误!', '$_FILES' => $_FILES ]; exit_return($return); } elseif($is_error === 2){ $return = [ 'error_code' => 10006, 'msg' => '提交到代理程序的文件太大!', '$_FILES' => $_FILES ]; exit_return($return); } else {} } // exit_return($files_data); $post_data = array_merge($post_data, $files_data); curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); } } // 注意:不同服务器端开发语言cookie对应session的id名是不同的:SessionID,ASPSESSIONID,ASP.NET_SessionId,JsessionId,PHPSESSID $lang_config = [ 'php' => 'PHPSESSID', 'asp' => 'ASPSESSIONID', 'aspx' => 'ASP.NET_SessionId', 'asp.net' => 'ASP.NET_SessionId', 'jsp' => 'JsessionId', 'default' => 'SessionID', ]; $url_lang = 'php'; // 被代理地址的服务器端开发语言对应的配置 // 设置cookie $cookie = ''; ////foreach($_COOKIE as $key => $value){【注意:高危使用,请谨慎使用$_COOKIE】 //// if($key == 'PHPSESSID'){ //// $key = $lang_config[$url_lang]; //// } //// $cookie.= $key . '=' . $value . ';'; ////} $session_id = substr(md5(date('Y-m-d')), 0, 26); // 请自定义 foreach ($lang_config as $value){ $cookie.= $value . '=' . $session_id . ';'; } if($cookie){ curl_setopt($ch, CURLOPT_COOKIE, $cookie); } // 参数为0表示不带头文件,为1表示带头文件 curl_setopt($ch, CURLOPT_HEADER, false); $output = curl_exec($ch); curl_close($ch); echo $output; exit; function exit_return($return_data) { header("content-Type: text/html; charset=UTF-8"); echo json_encode($return_data); exit; }