• 最近做广告联盟的一个项目,在页面插入广告代码时被广告插件给拦截了,这里简单的记录下解决方案。

方案一、代码直接写在页面上,不使用引入的方式。

  • 以前直接引入是这样的:
<script src="http://xxxxxxx"> </script>
  • 现在改成这样:
<script type="text/javascript">
//..................这里写src="http://xxxxxxx"那段js广告代码
</script>
  • 测试了下这种是没有被插件拦截的(不过老板说代码量太大了,人家站长不会复制的,所以我放弃了这种);

方案二、广告代码使用websocket方式返回,然后追加到页面上(我们使用的这个方案)。

  • 我在网上查到目前广告插件对websocket拦截的不是那么严,也有的网站实现过了,所以自己也来试试。
  • 首先来写段websocket代码,做服务端 webSocket.php:
<?phperror_reporting(E_ALL ^ E_NOTICE);
ob_implicit_flush();//地址与接口,即创建socket时需要服务器的IP和端口
$sk=new Sock('192.168.0.111',9090);//对创建的socket循环进行监听,处理数据
$sk->run();/*** 模拟post进行url请求* @param string $url* @param array $post_data*/function request_post($url = '', $post_data = array()) {//url为必传  如果该地址不需要参数就不传if (empty($url)) {return false;}if(!empty($post_data)){$params = '';foreach ( $post_data as $k => $v ) { $params.= "$k=" . urlencode($v). "&" ;// $params.= "$k=" . $v. "&" ;}$params = substr($params,0,-1);} $ch = curl_init();//初始化curlcurl_setopt($ch, CURLOPT_URL,$url);//抓取指定网页curl_setopt($ch, CURLOPT_HEADER, 0);//设置headercurl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上//curl_setopt($ch, CURLOPT_POST, 1);//post提交方式  linux不传参数会返回400 Bad Request 错误所以暂时注释掉  ,windows不会if(!empty($post_data))curl_setopt($ch, CURLOPT_POSTFIELDS, $params);$data = curl_exec($ch);//运行curlcurl_close($ch);return $data;}//下面是sock类
class Sock{public $sockets; //socket的连接池,即client连接进来的socket标志public $users;   //所有client连接进来的信息,包括socket、client名字等public $master;  //socket的resource,即前期初始化socket时返回的socket资源private $sda=array();   //已接收的数据private $slen=array();  //数据总长度private $sjen=array();  //接收数据的长度private $ar=array();    //加密keyprivate $n=array();public function __construct($address, $port){//创建socket并把保存socket资源在$this->master$this->master=$this->WebSocket($address, $port);error_log("Sock __construct ");//创建socket连接池$this->sockets=array($this->master);}//对创建的socket循环进行监听,处理数据    function run(){//死循环,直到socket断开while(true){$changes=$this->sockets;$write=NULL;$except=NULL;/*//这个函数是同时接受多个连接的关键,我的理解它是为了阻塞程序继续往下执行。socket_select ($sockets, $write = NULL, $except = NULL, NULL);$sockets可以理解为一个数组,这个数组中存放的是文件描述符。当它有变化(就是有新消息到或者有客户端连接/断开)时,socket_select函数才会返回,继续往下执行。 $write是监听是否有客户端写数据,传入NULL是不关心是否有写变化。 $except是$sockets里面要被排除的元素,传入NULL是”监听”全部。 最后一个参数是超时时间 如果为0:则立即结束 如果为n>1: 则最多在n秒后结束,如遇某一个连接有新动态,则提前返回 如果为null:如遇某一个连接有新动态,则返回*/socket_select($changes,$write,$except,NULL);foreach($changes as $sock){//如果有新的client连接进来,则if($sock==$this->master){//接受一个socket连接$client=socket_accept($this->master);//给新连接进来的socket一个唯一的ID$key=uniqid();$this->sockets[]=$client;  //将新连接进来的socket存进连接池$this->users[$key]=array('socket'=>$client,  //记录新连接进来client的socket信息'shou'=>false       //标志该socket资源没有完成握手);//否则1.为client断开socket连接,2.client发送信息}else{$len=0;$buffer='';//读取该socket的信息,注意:第二个参数是引用传参即接收数据,第三个参数是接收数据的长度do{$l=socket_recv($sock,$buf,1000,0);$len+=$l;$buffer.=$buf;}while($l==1000);//根据socket在user池里面查找相应的$k,即健ID$k=$this->search($sock);//如果接收的信息长度小于7,则该client的socket为断开连接if($len<7){//给该client的socket进行断开操作,并在$this->sockets和$this->users里面进行删除$this->send2($k);continue;}//判断该socket是否已经握手if(!$this->users[$k]['shou']){//如果没有握手,则进行握手处理$this->woshou($k,$buffer);}else{//走到这里就是该client发送信息了,对接受到的信息进行uncode处理$buffer = $this->uncode($buffer,$k);if($buffer==false){continue;}//error_log(" received buffer  " . $buffer);//如果不为空,则进行消息推送操作$this->send($k,$buffer);}}}}}//指定关闭$k对应的socketfunction close($k){//断开相应socketsocket_close($this->users[$k]['socket']);//删除相应的user信息unset($this->users[$k]);//重新定义sockets连接池$this->sockets=array($this->master);foreach($this->users as $v){$this->sockets[]=$v['socket'];}//输出日志$this->e("key:$k close");}//根据sock在users里面查找相应的$kfunction search($sock){foreach ($this->users as $k=>$v){if($sock==$v['socket'])return $k;}return false;}//传相应的IP与端口进行创建socket操作function WebSocket($address,$port){$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);//1表示接受所有的数据包socket_bind($server, $address, $port);socket_listen($server);$this->e('Server Started : '.date('Y-m-d H:i:s'));$this->e('Listening on   : '.$address.' port '.$port);return $server;}/** 函数说明:对client的请求进行回应,即握手操作* @$k clien的socket对应的健,即每个用户有唯一$k并对应socket* @$buffer 接收client请求的所有信息*/function woshou($k,$buffer){//截取Sec-WebSocket-Key的值并加密,其中$key后面的一部分258EAFA5-E914-47DA-95CA-C5AB0DC85B11字符串应该是固定的$buf  = substr($buffer,strpos($buffer,'Sec-WebSocket-Key:')+18);$key  = trim(substr($buf,0,strpos($buf,"\r\n")));$new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));//按照协议组合信息进行返回$new_message = "HTTP/1.1 101 Switching Protocols\r\n";$new_message .= "Upgrade: websocket\r\n";$new_message .= "Sec-WebSocket-Version: 13\r\n";$new_message .= "Connection: Upgrade\r\n";$new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";socket_write($this->users[$k]['socket'],$new_message,strlen($new_message));//对已经握手的client做标志$this->users[$k]['shou']=true;return true;}//解码函数function uncode($str,$key){$mask = array();  $data = '';  $msg = unpack('H*',$str);$head = substr($msg[1],0,2);  if ($head == '81' && !isset($this->slen[$key])) {  $len=substr($msg[1],2,2);$len=hexdec($len);//把十六进制的转换为十进制if(substr($msg[1],2,2)=='fe'){$len=substr($msg[1],4,4);$len=hexdec($len);$msg[1]=substr($msg[1],4);}else if(substr($msg[1],2,2)=='ff'){$len=substr($msg[1],4,16);$len=hexdec($len);$msg[1]=substr($msg[1],16);}$mask[] = hexdec(substr($msg[1],4,2));  $mask[] = hexdec(substr($msg[1],6,2));  $mask[] = hexdec(substr($msg[1],8,2));  $mask[] = hexdec(substr($msg[1],10,2));$s = 12;$n=0;}else if($this->slen[$key] > 0){$len=$this->slen[$key];$mask=$this->ar[$key];$n=$this->n[$key];$s = 0;}$e = strlen($msg[1])-2;for ($i=$s; $i<= $e; $i+= 2) {  $data .= chr($mask[$n%4]^hexdec(substr($msg[1],$i,2)));  $n++;  }  $dlen=strlen($data);if($len > 255 && $len > $dlen+intval($this->sjen[$key])){$this->ar[$key]=$mask;$this->slen[$key]=$len;$this->sjen[$key]=$dlen+intval($this->sjen[$key]);$this->sda[$key]=$this->sda[$key].$data;$this->n[$key]=$n;return false;}else{unset($this->ar[$key],$this->slen[$key],$this->sjen[$key],$this->n[$key]);$data=$this->sda[$key].$data;unset($this->sda[$key]);return $data;}}//与uncode相对function code($msg){$frame = array();  $frame[0] = '81';  $len = strlen($msg);if($len < 126){$frame[1] = $len<16?'0'.dechex($len):dechex($len);}else if($len < 65025){$s=dechex($len);$frame[1]='7e'.str_repeat('0',4-strlen($s)).$s;}else{$s=dechex($len);$frame[1]='7f'.str_repeat('0',16-strlen($s)).$s;}$frame[2] = $this->ord_hex($msg); $data = implode('',$frame);  return pack("H*", $data);  }function ord_hex($data)  {  $msg = '';  $l = strlen($data);  for ($i= 0; $i<$l; $i++) {  $msg .= dechex(ord($data{$i}));  }  return $msg;  }//用户加入或client发送信息function send($k,$msg){//将查询字符串解析到第二个参数变量中,以数组的形式保存如:parse_str("name=Bill&age=60",$arr)parse_str($msg,$g);$ar=array();$fromDate = json_decode($msg);error_log("json_decode(msg)[text] " . $fromDate->text);if($g['type']=='add'){//第一次进入添加聊天名字,把姓名保存在相应的users里面$this->users[$k]['name']=$g['ming'];$ar['type']='add';$ar['name']=$g['ming'];$key='all';}else{//发送信息行为,其中$g['key']表示面对大家还是个人,是前段传过来的信息$ar['nrong']=$g['nr'];$key=$g['key'];}$ar["requestUrl"] = $fromDate->text;//推送信息$this->send1($k,$ar,$key);}//对新加入的client推送已经在线的clientfunction getusers(){$ar=array();foreach($this->users as $k=>$v){$ar[]=array('code'=>$k,'name'=>$v['name']);}return $ar;}//$k 发信息人的socketID $key接受人的 socketID ,根据这个socketID可以查找相应的client进行消息推送,即指定client进行发送function send1($k,$ar,$key='all'){$ar['code1']=$key;$ar['code']=$k;$ar['time']=date('m-d H:i:s');//对发送信息进行编码处理$str = $this->code(json_encode($ar));//面对大家即所有在线者发送信息error_log("ar value " . json_encode($ar));if($key=='all'){$users=$this->users;//如果是add表示新加的clientif($ar['type']=='add'){$ar['type']='madd';$ar['users']=$this->getusers();        //取出所有在线者,用于显示在在线用户列表中$str1 = $this->code(json_encode($ar)); //单独对新client进行编码处理,数据不一样//对新client自己单独发送,因为有些数据是不一样的socket_write($users[$k]['socket'],$str1,strlen($str1));//上面已经对client自己单独发送的,后面就无需再次发送,故unsetunset($users[$k]);}//除了新client外,对其他client进行发送信息。数据量大时,就要考虑延时等问题了foreach($users as $v){socket_write($v['socket'],$str,strlen($str));}}else{//单独对个人发送信息,即双方聊天//socket_write($this->users[$k]['socket'],$str,strlen($str));error_log(" ar[requestUrl]" .$ar["requestUrl"]);//发起请求得到广告$responseBody = request_post($ar["requestUrl"], array());$arrays = array();$arrays["responseBody"] = $responseBody;$str = $this->code(json_encode($arrays));//error_log("responseBody ".$str["responseBody"]);socket_write($this->users[$k]['socket'],$str,strlen($str));//socket_write($this->users[$key]['socket'],$str,strlen($str));}}//用户退出向所用client推送信息function send2($k){$this->close($k);$ar['type']='rmove';$ar['nrong']=$k;$this->send1(false,$ar,'all');}//记录日志function e($str){//$path=dirname(__FILE__).'/log.txt';$str=$str."\n";//error_log($str,3,$path);//编码处理echo iconv('utf-8','gbk//IGNORE',$str);}}echo "1";
?>

这代码是抄的,然后改了点东西。

  • 服务端有了,再来写客户端的东西。
//这段代码需要引入jQuery<script type="text/javascript">//ws连接var websocket;/****zhouzhongqing* 2018年6月1日14:50:02* 发送消息* */function sendHeartMessage(message) {console.log("发送消息");var data = {};data["to"] = 0;data["text"] = message;websocket.send(JSON.stringify(data));}/*** zhouzhongqing* 2018年10月23日15:58:09* 创建websocket连接* **/function createWebSocket() {//webSocket地址var wsLocation = "ws://192.168.0.111:9090";try {// 指定websocket路径if ('WebSocket' in window) {websocket = new WebSocket(wsLocation);} else if ('MozWebSocket' in window) {websocket = new MozWebSocket(wsLocation);} else {websocket = new SockJS(wsLocation);}initEventHandle();}catch (e){console.log("createWebSocket error " + e);}}function initEventHandle(){websocket.onopen = function (event) {console.log("open start");//这是把广告地址发给websocketsendHeartMessage("http://zyiis.xxxx.com/s.php?id=12");console.log("open end");};websocket.onclose = function () {console.log("ws 关闭 !" + new Date().toUTCString());};websocket.onerror = function () {console.log(" ws连接错误!" + new Date().toUTCString());};websocket.onmessage = function (event) {var data = JSON.parse(event.data);//console.log(data);var responseBody = data.responseBody;//返回的js追加到body标签里$("body").append("<script>"+responseBody+"<\/script>");websocket.close();};}$(document).ready(function () {createWebSocket();});</script>
  • 基本思路就是这样实现的,下面一步就是封装代码。
  • 封装web_socket.js
//ws连接
var websocket;//任务个数
var taskCount = 0;//判断是否存在websocket连接
var isExistenceWs = false;/**** 有可能有多个广告,所有后面的稍等下再发送* */
function createWebSocketTask(message) {taskCount++;if(isExistenceWs){setTimeout("sendHeartMessage('"+message+"')",taskCount + 1000);}else {createWebSocket(message );}
}setInterval("closeWebSocketConnection()",3000);/**** 关闭socket连接* */
function closeWebSocketConnection() {if(isExistenceWs && taskCount == 0){setTimeout(" websocket.close()",3000);}
}/****zhouzhongqing* 2018年6月1日14:50:02* 发送 消息* */
function sendHeartMessage(message) {console.log("发送消息");var data = {};data["to"] = 0;data["text"] = message;websocket.send(JSON.stringify(data));
}/*** zhouzhongqing* 2018年10月23日15:58:09* 创建websocket连接* **/
function createWebSocket(message) {//webSocket地址var wsLocation = "ws://192.168.0.111:9090";try {// 指定websocket路径if ('WebSocket' in window) {websocket = new WebSocket(wsLocation);} else if ('MozWebSocket' in window) {websocket = new MozWebSocket(wsLocation);} else {websocket = new SockJS(wsLocation);}initEventHandle(message);isExistenceWs = true;}catch (e){console.log("createWebSocket error " + e);isExistenceWs = false;}
}function initEventHandle(message){websocket.onopen = function (event) {console.log("open start");sendHeartMessage(message);console.log("open end");};websocket.onclose = function () {console.log("ws 关闭 !" + new Date().toUTCString());};websocket.onerror = function () {console.log(" ws连接错误!" + new Date().toUTCString());};websocket.onmessage = function (event) {//收到消息则减-taskCount--;var data = JSON.parse(event.data);//console.log(data);var responseBody = data.responseBody;//考虑到有的网站网页有可能不支持jQuery所以用这种方式追加var newScript = document.createElement("script");newScript.setAttribute("type","text/javascript");newScript.innerHTML = responseBody;document.getElementsByTagName("body")[0].appendChild(newScript);//$("body").append("<script>"+responseBody+"<\/script>");//websocket.close();};
}
  • 然后js页面调用,这也是站长要在页面加入的代码。
<!--注意这个web_socket.js一个页面只引入一次-->
<script src="http://xxxxxxx/js/web_socket.js"></script><script type="text/javascript">createWebSocketTask("http://zyiis.xxxxx.com/s.php?id=12");</script><script type="text/javascript">createWebSocketTask("http://zyiis.xxxxx.com/s.php?id=11");</script>
  • 最后运行效果:

    • 运行websocket服务端

    • 页面:

绕过广告拦截插件的解决方案相关推荐

  1. 使用WebSocket绕过广告屏蔽插件

    2019独角兽企业重金招聘Python工程师标准>>> 现在网络上的广告真的是无所不用其极,在网上冲浪,稍不留神,随时随地都会碰上广告,于是广告屏蔽这个需求,就应运而生了.古语云,道 ...

  2. AdGuard广告拦截插件V3.6.6

    介绍: AdGuard AdBlocker 是一款广告拦截插件,用以对抗各式广告与弹窗.可以拦截绝大部分常见网站的广告. 例如视频广告,插播广告和浮动广告.从而实现加速页面载入,节省带宽,屏蔽广告和弹 ...

  3. Chrome上最好用的广告拦截插件:AdBlock

    Chrome上最好用的广告拦截插件:AdBlock AdBlock,是一款广告拦截插件,自动拦截网页中广告.广告拦截并非100%准确,因此它提供了个性化设置的功能. 一个页面如果被"误伤&q ...

  4. 最强chrome、edge的广告拦截插件

    最强chrome.edge的广告拦截插件 对于浏览器的广告是非常烦人的,尤其是使用百度搜索引擎时,总会在右侧出现百度热搜这样的东西,有时不经意间就会被某些热搜吸引.本来想搜索一些内容,结果被热搜等耗费 ...

  5. 【插件】浏览器广告拦截插件| 浏览器搜索广告横飞怎么办

    文章目录 浏览器广告拦截插件| 浏览器搜索广告横飞怎么办 一.效果 二.安装 浏览器广告拦截插件| 浏览器搜索广告横飞怎么办 浏览器广告横飞怎么办?今天教你一招解决!很多小伙伴说自己用的浏览器总是有广 ...

  6. 搜狗浏览器广告拦截插件_拦截烦人的网页广告,增加上网体验

    本号所有资源版权归原作者所有,如有侵权请加小编微信删除.本号免费分享,仅供学习交流,下载后24小时内请自觉删除,切勿用于商业用途,否则后果自负! 今天重新整理分享几大主流浏览器和IE浏览器拦截广告的方 ...

  7. 记一次被浏览器广告拦截插件坑死的经历:adp和ad插件把jsp页面中div显示的图片当作广告拦截!!

    没有任何显示,也没有任何报错,f12中也已经加载了图片等内容,又把chrome换到firfox,但是还是没用,因为我都装了ad插件,我真想爆粗口,因为ad插件也显示没有拦截到广告.经过查错一次又一次重 ...

  8. 广告拦截器:不要与他们战斗; 了解他们

    According to a study called Adblocking goes mainstream, published in September by PageFair, a provid ...

  9. token拦截器阻止连接_如何防止广告拦截器阻止您的分析数据

    token拦截器阻止连接 TL;DR There's dataunlocker.com service coming soon (subscribe!), along with the open-so ...

  10. 错误,误解和攻击:分析广告拦截系统的众包过程

    错误,误解和攻击:分析广告拦截系统的众包过程 "众包"(crowdsourcing):这一概念是由美国<连线>杂志的记者杰夫·豪(Jeff Howe)在 2006年6月 ...

最新文章

  1. 【网络编程】MarioTCP 流程图(一)
  2. CES线下展回归在即:飞行汽车外骨骼智能戒指吸足眼球
  3. 执行srvctl报错 :error while loading shared libraries: libpthread.so.0:
  4. servlet解析演进(2-1)
  5. 数据结构与算法之二叉搜索树
  6. cubic差值matlab,matlab自带的插值函数interp1的四种插值方法
  7. [cocos2dx]斗地主制作之洗牌算法
  8. 【转】修改UCGUI源代码以支持多个独立窗体的说明
  9. 反编译那些事儿(六)—所编译得.class文件带有$符号
  10. 算法:分离链表为两部分,小于某个值都在左边,大于等于某个值在右边 Partition List
  11. PXE启动错误代码一览表
  12. 五款优秀免费的在线抠图工具
  13. 由两个重要极限推导常见等价无穷小以及常见导数公式
  14. 浅谈智能DNS云解析(二)
  15. python字符串加减乘除_从字符串解析加减乘除符号
  16. iOS 开发 申请299美金企业开发账号
  17. 护照阅读器助力旅行社快捷录入
  18. 安装oh my zsh后出现的目录权限问题
  19. Canon F-789sga 计算器
  20. 遥感测深方法综述(二)CZMIL 机载LiDAR 测深系统

热门文章

  1. libcurl基础教程及封装(支持同步异步请求,支持多线程下载,支持https)
  2. Windows PE的DIY你都会:那你的电脑知识已经超越了90%的人
  3. 自考《离散数学》题型总结
  4. 计算机视觉——SIFT算法
  5. 教你炒股票19:学习缠中说禅技术分析理论的关键
  6. Linux elf文件分析
  7. android电池管理软件,四款安卓手机电池管理软件横测
  8. Axure RP 9 下载、汉化及最新授权码
  9. Oracle连接pb,PB内置Oracle数据库接口的使用方法
  10. 软件实施工程师到底是做什么的?