竹磬网-邵珠庆の日记 生命只有一次,你可以用它来做些更多伟大的事情–Make the world a little better and easier


254月/190

CA证书扫盲和原理

发布在 邵珠庆

1.什么是CA证书。

看过一些博客,写的比较形象具体。
◇ 普通的介绍信
想必大伙儿都听说过介绍信的例子吧?假设 A 公司的张三先生要到 B 公司去拜访,但是 B 公司的所有人都不认识他,他咋办捏?常用的办法是带公司开的一张介绍信,在信中说:兹有张三先生前往贵公司办理业务,请给予接洽......云云。然后在信上敲上A公司的公章。
张三先生到了 B 公司后,把介绍信递给 B 公司的前台李四小姐。李小姐一看介绍信上有 A 公司的公章,而且 A 公司是经常和 B 公司有业务往来的,这位李小姐就相信张先生不是歹人了。
这里,A公司就是CA证书
◇ 引入中介机构的介绍信
好,回到刚才的话题。如果和 B 公司有业务往来的公司很多,每个公司的公章都不同,那前台就要懂得分辨各种公章,非常滴麻烦。所以,有某个中介公司 C,发现了这个商机。C公司专门开设了一项“代理公章”的业务。
今后,A 公司的业务员去 B 公司,需要带2个介绍信:
介绍信1
含有 C 公司的公章及 A 公司的公章。并且特地注明:C 公司信任 A 公司。
介绍信2
仅含有 A 公司的公章,然后写上:兹有张三先生前往贵公司办理业务,请给予接洽......云云。
某些不开窍的同学会问了,这样不是增加麻烦了吗?有啥好处捏?
主要的好处在于,对于接待公司的前台,就不需要记住各个公司的公章分别是啥样子的;他/她只要记住中介公司 C 的公章即可。当他/她拿到两份介绍信之后,先对介绍信1的 C 公章,验明正身;确认无误之后,再比对介绍信1和介绍信2的两个 A 公章是否一致。如果是一样的,那就可以证明介绍信2是可以信任的了。
◇ 什么是证书?
“证书”洋文也叫“digital certificate”或“public key certificate”(专业的解释看“这里”)。
它是用来证明某某东西确实是某某东西的东西(是不是像绕口令?)。通俗地说,证书就好比例子里面的公章。通过公章,可以证明该介绍信确实是对应的公司发出的。
理论上,人人都可以找个证书工具,自己做一个证书。那如何防止坏人自己制作证书出来骗人捏?请看后续 CA 的介绍。
◇ 什么是CA?
CA是Certificate Authority的缩写,也叫“证书授权中心”。(专业的解释看“这里”)
它是负责管理和签发证书的第三方机构,就好比例子里面的中介——C 公司。一般来说,CA必须是所有行业和所有公众都信任的、认可的。因此它必须具有足够的权威性。就好比A、B两公司都必须信任C公司,才会找 C 公司作为公章的中介。
◇ 什么是CA证书?
CA 证书,顾名思义,就是CA颁发的证书。
前面已经说了,人人都可以找工具制作证书。但是你一个小破孩制作出来的证书是没啥用处的。因为你不是权威的CA机关,你自己搞的证书不具有权威性。
这就好比上述的例子里,某个坏人自己刻了一个公章,盖到介绍信上。但是别人一看,不是受信任的中介公司的公章,就不予理睬。坏蛋的阴谋就不能得逞啦。
文本后续提及的证书,若无特殊说明,均指 CA 证书。

2.证书的签发过程:

a.服务方 S 向第三方机构CA提交公钥、组织信息、个人信息(域名)等信息并申请认证;
b.CA 通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等;
c.如信息审核通过,CA 会向申请者签发认证文件-证书。
证书包含以下信息:申请者公钥、申请者的组织信息和个人信息、签发机构 CA 的信息、有效时间、证书序列号等信息的明文,同时包含一个签名;
签名的产生算法:首先,使用散列函数计算公开的明文信息的信息摘要,然后,采用 CA 的私钥对信息摘要进行加密,密文即签名;
d.客户端 C 向服务器 S 发出请求时,S 返回证书文件;
e.客户端 C 读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后,利用对应 CA 的公钥解密签名数据,对比证书的信息摘要,如果一致,则可以确认证书的合法性,即公钥合法;
f.客户端然后验证证书相关的域名信息、有效时间等信息;
g.客户端会内置信任 CA 的证书信息(包含公钥),如果CA不被信任,则找不到对应 CA 的证书,证书也会被判定非法。
在这个过程注意几点:
1.申请证书不需要提供私钥,确保私钥永远只能服务器掌握;
2.证书的合法性仍然依赖于非对称加密算法,证书主要是增加了服务器信息以及签名;
3.内置 CA 对应的证书称为根证书,颁发者和使用者相同,自己为自己签名,即自签名证书;
4.证书=公钥+申请者与颁发者信息+签名;

3.http存在的问题(引用:http://blog.csdn.net/wangjun5159/article/details/51510594)

http通信存在的问题
a.容易被监听
http通信都是明文,数据在客户端与服务器通信过程中,任何一点都可能被劫持。比如,发送了银行卡号和密码,hacker劫取到数据,就能看到卡号和密码,这是很危险的
b.被伪装
http通信时,无法保证通行双方是合法的,通信方可能是伪装的。比如你请求www.taobao.com,你怎么知道返回的数据就是来自淘宝,中间人可能返回数据伪装成淘宝。
c.被篡改
hacker中间篡改数据后,接收方并不知道数据已经被更改

共享密钥加密和公开密钥加密,后续内容的需要,这里插播一段共享密钥加密和公开密钥加密
共享密钥加密 :共享密钥的加密密钥和解密密钥是相同的,所以又称为对称密钥
公开密钥加密 :加密算法是公开的,密钥是保密的。公开密钥分为私有密钥和公有密钥,公有密钥是公开的,任何人(客户端)都可以获取,客户端使用公有密钥加密数据,服务端用私有密钥解密数据。
异同
共享密钥加密与公开密钥加密相比,加解密处理速度快,但公开密钥更适应互联网下使用
https解决的问题
https很好的解决了http的三个缺点(被监听、被篡改、被伪装),https不是一种新的协议,它是http+SSL(TLS)的结合体,SSL是一种独立协议,所以其它协议比如smtp等也可以跟ssl结合。https改变了通信方式,它由以前的http—–>tcp,改为http——>SSL—–>tcp;https采用了共享密钥加密+公开密钥加密的方式
防监听 :数据是加密的,所以监听得到的数据是密文,hacker看不懂。
防伪装 :伪装分为客户端伪装和服务器伪装,通信双方携带证书,证书相当于身份证,有证书就认为合法,没有证书就认为非法,证书由第三方颁布,很难伪造
防篡改 :https对数据做了摘要,篡改数据会被感知到。hacker即使从中改了数据也白搭。
https连接过程
客户端发送请求到服务器端
服务器端返回证书和公开密钥,公开密钥作为证书的一部分而存在
客户端验证证书和公开密钥的有效性,如果有效,则生成共享密钥并使用公开密钥加密发送到服务器端
服务器端使用私有密钥解密数据,并使用收到的共享密钥加密数据,发送到客户端
客户端使用共享密钥解密数据
SSL加密建立………
客户端认证的通信的过程
客户端需要认证的过程跟服务器端需要认证的过程基本相同,并且少了最开始的两步。这种情况都是证书存储在客户端,并且应用场景比较少,一般金融才使用,比如支付宝、银行客户端都需要安装证书
后续的问题
怎样保证公开密钥的有效性
你也许会想到,怎么保证客户端收到的公开密钥是合法的,不是伪造的,证书很好的完成了这个任务。证书由权威的第三方机构颁发,并且对公开密钥做了签名。
https的缺点
https保证了通信的安全,但带来了加密解密消耗计算机cpu资源的问题 ,不过,有专门的https加解密硬件服务器
各大互联网公司,百度、淘宝、支付宝、知乎都使用https协议,为什么?
支付宝涉及到金融,所以出于安全考虑采用https这个,可以理解,为什么百度、知乎等也采用这种方式?为了防止运营商劫持!http通信时,运营商在数据中插入各种广告,用户看到后,怒火发到互联网公司,其实这些坏事都是运营商(移动、联通、电信)干的,用了https,运营商就没法插播广告篡改数据了。

4.比较完整的过程:

1. 客户端发起HTTPS请求
这个没什么好说的,就是用户在浏览器里输入一个https网址,然后连接到server的443端口。
2. 服务端的配置
采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面(startssl就是个不错的选择,有1年的免费服务)。这套证书其实就是一对公钥和私钥。如果对公钥和私钥不太理解,可以想象成一把钥匙和一个锁头,只是全世界只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。
3. 传送证书
这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。
4. 客户端解析证书
这部分工作是有客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随机值。然后用证书对该随机值进行加密。就好像上面说的,把随机值用锁头锁起来,这样除非有钥匙,不然看不到被锁住的内容。
5. 传送加密信息
这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。
6. 服务段解密信息
服务端用私钥解密后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进行对称加密。所谓对称加密就是,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,所以只要加密算法够彪悍,私钥够复杂,数据就够安全。
7. 传输加密后的信息
这部分信息是服务段用私钥加密后的信息,可以在客户端被还原。
8. 客户端解密信息
客户端用之前生成的私钥解密服务段传过来的信息,于是获取了解密后的内容。整个过程第三方即使监听到了数据,也束手无策。

5.总结整个过程:

1.服务器向CA机构获取证书(假设这个证书伪造不了),当浏览器首次请求服务器的时候,服务器返回证书给浏览器。(证书包含:公钥+申请者与颁发者的相关信息+签名)
2.浏览器得到证书后,开始验证证书的相关信息,证书有效(没过期等)。(验证过程,比较复杂,详见上文)。
3.验证完证书后,如果证书有效,客户端是生成一个随机数,然后用证书中的公钥进行加密,加密后,发送给服务器,服务器用私钥进行解密,得到随机数。之后双方便开始用该随机数作为钥匙,对要传递的数据进行加密、解密。

28月/170

介绍一下GFW的工作原理和封锁技术

发布在 邵珠庆

GFW是Great Fire Wall的缩写,即“长城防火墙”。这个工程由若干个部分组成,实现不同功能。长城防火墙主要指TG监控和过滤互联网内容的软硬件系统,由服务器和路由器等设备,加上相关的应用程序所构成。

首先,需要强调的是,由于中国网络审查广泛,中国国内含有“不合适”内容的的网站,会受到政府直接的行政干预,被要求自我审查、自我监管,乃至关闭,所以GFW的主要作用在于分析和过滤中国境内外网络的资讯互相访问。

GFW对网络内容的过滤和分析是双向的,GFW不仅针对国内读者访问中国境外的网站进行干扰,也干扰国外读者访问主机在中国大陆的网站。

一 关键字过滤阻断

关键字过滤系统。此系统能够从出口网关收集分析信息,过滤、嗅探指定的关键字。主要针对HTTP的默认端口:80端口,因为HTTP传播的内容是明文的内容,没有经过加密,而GFW是一个IDS(Intrusion detection system)。普通的关键词如果出现在HTTP请求报文的头部(如“Host: www.youtube.com”)时,则会马上伪装成对方向连接两端的计算机发送RST包(reset)干扰两者正常的TCP连接,进而使请求的内容无法继续查看。如果GFW在数据流中发现了特殊的内文关键词(如轮子,达赖等)时,其也会试图打断当前的连接,从而有时会出现网页开启一部分后突然停止的情况。在任何阻断发生后,一般在随后的90秒内同一IP地址均无法浏览对应IP地址相同端口上的内容。

二 IP地址封锁

IP地址封锁是GFW通过路由器来控制的,在通往国外的最后一个网关上加上一条伪造的路由规则,导致通往某些被屏蔽的网站的所有IP数据包无法到达。路由器的正常工作方式是学习别的路由器广播的路由规则,遇到符合已知的IP转发规则的数据包,则按已经规则发送,遇到未知规则IP的数据,则转发到上一级网关。

而GFW对于境外(中国大陆以外)的XX网站会采取独立IP封锁技术。然而部分XX网站使用的是由虚拟主机服务提供商提供的多域名、单(同)IP的主机托管服务,这就会造成了封禁某个IP地址,就会造成所有使用该服务提供商服务的其它使用相同IP地址服务器的网站用户一同遭殃,就算是正常的网站,也不能幸免。其中的内容可能并无不当之处,但也不能在中国大陆正常访问。现在GFW通常会将包含XX信息的网站或网页的URL加入关键字过滤系统,并可以防止民众透过普通海外HTTP代理服务器进行访问。

三 特定端口封锁

GFW会丢弃特定IP地址上特定端口的所有数据包,使该IP地址上服务器的部分功能(如SSH的22、VPN的1723或SSL的443端口等)无法在中国大陆境内正常使用。

在中国移动、中国联通等部分ISP(手机IP段),所有的PPTP类型的VPN都被封锁。

2011年3月起,GFW开始对Google部分服务器的IP地址实施自动封锁(按时间段)某些端口,按时段对www.google.com(用户登录所有Google服务时需此域名加密验证)和mail.google.com的几十个IP地址的443端口实施自动封锁,具体是每10或15分钟可以连通,接着断开,10或15分钟后再连通,再断开,如此循环,令中国大陆用户和Google主机之间的连接出现间歇性中断,使其各项服务出现问题。GFW这样的封锁手法很高明,因为Gmail并非被完全阻断,这令问题看上去好像出自Google本身。这就是你们认为Google抽风的原因。

四 SSL连接阻断

GFW会阻断特定网站的SSL加密连接,方法是通过伪装成对方向连接两端的计算机发送RST包(RESET)干扰两者间正常的TCP连接,进而打断与特定IP地址之间的SSL(HTTPS,443端口)握手(如Gmail、Google文件、Google网上论坛等的SSL加密连接),从而导致SSL连接失败。

当然由于SSL本身的特点,这并不意味着与网站传输的内容可被破译。

五 DNS劫持和污染

GFW主要采用DNS劫持和污染技术,使用Cisco提供的IDS系统来进行域名劫持,防止访问被过滤的网站,2002年Google被封锁期间其域名就被劫持到百度。中国部分ISP也会通过此技术插入广告。

对于含有多个IP地址或经常变更IP地址逃避封锁的域名,GFW通常会使用此方法进行封锁。具体方法是当用户向DNS服务器提交域名请求时,DNS返回虚假(或不解析)的IP地址。

全球一共有13组根域名服务器(Root Server),目前中国大陆有F、I这2个根域DNS镜像,但现在均已因为多次DNS污染外国网络,而被断开与国际互联网的连接。

DNS劫持和污染是针对某些网站的最严重的干扰。

干扰的方式有两种:

一种是通过网络服务提供商(Internet Service Provider)提供的DNS服务器进行DNS欺骗,当人们访问某个网站时,需要要把域名转换为一个IP地址,DNS服务器负责将域名转换为IP地址,中国大陆的ISP接受通信管理局的屏蔽网站的指令后在DNS服务器里加入某些特定域名的虚假记录,当使用此DNS服务器的网络用户访问此特定网站时,DNS服务便给出虚假的IP地址,导致访问网站失败,甚至返回ISP运营商提供的出错页面和广告页面。

另一种是GFW在DNS查询使用的UDP的53端口上根据blacklist进行过滤,遇到通往国外的使用UDP53端口进行查询的DNS请求,就返回一个虚假的IP地址。

104月/170

域名解析生效原理及时间

发布在 邵珠庆

一、域名解析生效原理

域名解析生效的过程,是域名与IP绑定的过程。当解析生效后,用户访问域名时的实现机制是:由 DNS 服务器询问域名指向了哪个 IP 地址,再由 DNS 服务器告诉客户端打开对应网站空间。

万网域名的解析生效,第一步是万网 DNS 必须首先生效,然后等待世界各地 Local DNS 生效,可以通俗的理解为各大电信运营管理的 DNS 需要及时同步万网 DNS 解析记录,才能最终生效。 网站是否能访问,直接相关的是 Local DNS,万网云解析都是实时生效的,一般只需几秒即可同步到各地 Local DNS 上,但各地 Local DNS 均有缓存机制,解析的最终生效取决于各运营商刷新时间。见下图。

出于对域名安全的保证,万网云解析的解析记录数据并非直接修改 DNS 后台数据,而是修改万网控制中心数据,然后同步至DNS服务器。从而避免了因DNS服务器漏洞所造成的安全隐患。

二、域名解析生效时间

全球有无数的互联网节点与 DNS 服务器,在设置域名解析记录后,将此结果同步至全球各个 DNS 服务器,这一过程所需要的时间即为解析生效时间。

域名解析记录生效的时间可以分为如下三种情况:

1、新增解析记录生效时间

使用万网云解析新增解析记录,实时生效。 

2、修改解析记录生效时间 

使用万网云解析修改解析记录,最终生效时间取决于各地运营商的 DNS 服务器缓存刷新时间(各地 ISP 的 DNS 上缓存了修改前的解析记录,不会实时更新),一般情况下等同于您之前设置解析时的 TTL 时间。例如你之前的解析设置中 TTL 值为 10 分钟,修改解析后将在 10 分钟内实现全球生效。

3、修改 DNS 后,设置解析记录生效时间 

如修改了 DNS 地址后使用万网云解析修改解析记录,最终生效时间同样取决于各地运营商的DNS服务器缓存刷新时间。但各地 DNS 的刷新时间不一致,且刷新时间较长,导致解析在全球生效时间需要 24~48 小时。(.com 等国际域名需要 48 小时,.cn 等国内域名需要 24 小时)

 

https://help.aliyun.com/knowledge_detail/39837.html

214月/160

二维码的生成细节和原理

发布在 邵珠庆

二维码又称QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型:比如:字符,数字,日文,中文等等。这两天学习了一下二维码图片生成的相关细节,觉得这个玩意就是一个密码算法,在此写一这篇文章 ,揭露一下。供好学的人一同学习之。

关于QR Code Specification,可参看这个PDF:http://raidenii.net/files/datasheets/misc/qr_code.pdf 

基础知识

首先,我们先说一下二维码一共有40个尺寸。官方叫版本Version。Version 1是21 x 21的矩阵,Version 2是 25 x 25的矩阵,Version 3是29的尺寸,每增加一个version,就会增加4的尺寸,公式是:(V-1)*4 + 21(V是版本号) 最高Version 40,(40-1)*4+21 = 177,所以最高是177 x 177 的正方形。

下面我们看看一个二维码的样例:

 

 

定位图案

  • Position Detection Pattern是定位图案,用于标记二维码的矩形大小。这三个定位图案有白边叫Separators for Postion Detection Patterns。之所以三个而不是四个意思就是三个就可以标识一个矩形了。
  • Timing Patterns也是用于定位的。原因是二维码有40种尺寸,尺寸过大了后需要有根标准线,不然扫描的时候可能会扫歪了。
  • Alignment Patterns 只有Version 2以上(包括Version2)的二维码需要这个东东,同样是为了定位用的。

功能性数据

  • Format Information 存在于所有的尺寸中,用于存放一些格式化数据的。
  • Version Information 在 >= Version 7以上,需要预留两块3 x 6的区域存放一些版本信息。

数据码和纠错码

  • 除了上述的那些地方,剩下的地方存放 Data Code 数据码 和 Error Correction Code 纠错码。

数据编码

我们先来说说数据编码。QR码支持如下的编码:

Numeric mode 数字编码,从0到9。如果需要编码的数字的个数不是3的倍数,那么,最后剩下的1或2位数会被转成4或7bits,则其它的每3位数字会被编成 10,12,14bits,编成多长还要看二维码的尺寸(下面有一个表Table 3说明了这点)

Alphanumeric mode 字符编码。包括 0-9,大写的A到Z(没有小写),以及符号$ % * + – . / : 包括空格。这些字符会映射成一个字符索引表。如下所示:(其中的SP是空格,Char是字符,Value是其索引值) 编码的过程是把字符两两分组,然后转成下表的45进制,然后转成11bits的二进制,如果最后有一个落单的,那就转成6bits的二进制。而编码模式和字符的个数需要根据不同的Version尺寸编成9, 11或13个二进制(如下表中Table 3)

 

Byte mode, 字节编码,可以是0-255的ISO-8859-1字符。有些二维码的扫描器可以自动检测是否是UTF-8的编码。

Kanji mode 这是日文编码,也是双字节编码。同样,也可以用于中文编码。日文和汉字的编码会减去一个值。如:在0X8140 to 0X9FFC中的字符会减去8140,在0XE040到0XEBBF中的字符要减去0XC140,然后把结果前两个16进制位拿出来乘以0XC0,然后再加上后两个16进制位,最后转成13bit的编码。如下图示例:

 

Extended Channel Interpretation (ECI) mode 主要用于特殊的字符集。并不是所有的扫描器都支持这种编码。

Structured Append mode 用于混合编码,也就是说,这个二维码中包含了多种编码格式。

FNC1 mode 这种编码方式主要是给一些特殊的工业或行业用的。比如GS1条形码之类的。

简单起见,后面三种不会在本文 中讨论。

下面两张表中,

  • Table 2 是各个编码格式的“编号”,这个东西要写在Format Information中。注:中文是1101
  • Table 3 表示了,不同版本(尺寸)的二维码,对于,数字,字符,字节和Kanji模式下,对于单个编码的2进制的位数。(在二维码的规格说明书中,有各种各样的编码规范表,后面还会提到)

 

下面我们看几个示例,

示例一:数字编码

在Version 1的尺寸下,纠错级别为H的情况下,编码: 01234567

1. 把上述数字分成三组: 012 345 67

2. 把他们转成二进制:  012 转成 0000001100;  345 转成 0101011001;  67 转成 1000011。

3. 把这三个二进制串起来: 0000001100 0101011001 1000011

4. 把数字的个数转成二进制 (version 1-H是10 bits ): 8个数字的二进制是 0000001000

5. 把数字编码的标志0001和第4步的编码加到前面:  0001 0000001000 0000001100 0101011001 1000011

示例二:字符编码

在Version 1的尺寸下,纠错级别为H的情况下,编码: AC-42

1. 从字符索引表中找到 AC-42 这五个字条的索引 (10,12,41,4,2)

2. 两两分组: (10,12) (41,4) (2)

3.把每一组转成11bits的二进制:

(10,12) 10*45+12 等于 462 转成 00111001110

(41,4) 41*45+4 等于 1849 转成 11100111001

(2) 等于 2 转成 000010

4. 把这些二进制连接起来:00111001110 11100111001 000010

5. 把字符的个数转成二进制 (Version 1-H为9 bits ): 5个字符,5转成 000000101

6. 在头上加上编码标识 0010 和第5步的个数编码:  0010 000000101 00111001110 11100111001 000010

结束符和补齐符

假如我们有个HELLO WORLD的字符串要编码,根据上面的示例二,我们可以得到下面的编码,

编码 字符数 HELLO WORLD的编码
0010 000001011 01100001011 01111000110 10001011100 10110111000 10011010100 001101

我们还要加上结束符:

编码 字符数 HELLO WORLD的编码 结束
0010 000001011 01100001011 01111000110 10001011100 10110111000 10011010100 001101 0000

按8bits重排

如果所有的编码加起来不是8个倍数我们还要在后面加上足够的0,比如上面一共有78个bits,所以,我们还要加上2个0,然后按8个bits分好组:

00100000   01011011   00001011   01111000   11010001   01110010   11011100   01001101   01000011   01000000

补齐码(Padding Bytes)

最后,如果如果还没有达到我们最大的bits数的限制,我们还要加一些补齐码(Padding Bytes),Padding Bytes就是重复下面的两个bytes:11101100 00010001 (这两个二进制转成十进制是236和17,我也不知道为什么,只知道Spec上是这么写的)关于每一个Version的每一种纠错级别的最大Bits限制,可以参看QR Code Spec的第28页到32页的Table-7一表。

假设我们需要编码的是Version 1的Q纠错级,那么,其最大需要104个bits,而我们上面只有80个bits,所以,还需要补24个bits,也就是需要3个Padding Bytes,我们就添加三个,于是得到下面的编码:

00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01000000 11101100 00010001 11101100

上面的编码就是数据码了,叫Data Codewords,每一个8bits叫一个codeword,我们还要对这些数据码加上纠错信息。

纠错码

上面我们说到了一些纠错级别,Error Correction Code Level,二维码中有四种级别的纠错,这就是为什么二维码有残缺还能扫出来,也就是为什么有人在二维码的中心位置加入图标。

错误修正容量
L水平 7%的字码可被修正
M水平 15%的字码可被修正
Q水平 25%的字码可被修正
H水平 30%的字码可被修正

那么,QR是怎么对数据码加上纠错码的?首先,我们需要对数据码进行分组,也就是分成不同的Block,然后对各个Block进行纠错编码,对于如何分组,我们可以查看QR Code Spec的第33页到44页的Table-13到Table-22的定义表。注意最后两列:

  • Number of Error Code Correction Blocks :需要分多少个块。
  • Error Correction Code Per Blocks:每一个块中的code个数,所谓的code的个数,也就是有多少个8bits的字节。

 

举个例子:上述的Version 5 + Q纠错级:需要4个Blocks(2个Blocks为一组,共两组),头一组的两个Blocks中各15个bits数据 + 各 9个bits的纠错码(注:表中的codewords就是一个8bits的byte)(再注:最后一例中的(c, k, r )的公式为:c = k + 2 * r,因为后脚注解释了:纠错码的容量小于纠错码的一半)

下图给一个5-Q的示例(因为二进制写起来会让表格太大,所以,我都用了十进制,我们可以看到每一块的纠错码有18个codewords,也就是18个8bits的二进制数)

数据 对每个块的纠错码
1 1 67 85 70 134 87 38 85 194 119 50 6 18 6 103 38 213 199 11 45 115 247 241 223 229 248 154 117 154 111 86 161 111 39
2 246 246 66 7 118 134 242 7 38 86 22 198 199 146 6 87 204 96 60 202 182 124 157 200 134 27 129 209 17 163 163 120 133
2 1 182 230 247 119 50 7 118 134 87 38 82 6 134 151 50 7 148 116 177 212 76 133 75 242 238 76 195 230 189 10 108 240 192 141
2 70 247 118 86 194 6 151 50 16 236 17 236 17 236 17 236 235 159 5 173 24 147 59 33 106 40 255 172 82 2 131 32 178 236

注:二维码的纠错码主要是通过Reed-Solomon error correction(里德-所罗门纠错算法)来实现的。对于这个算法,对于我来说是相当的复杂,里面有很多的数学计算,比如:多项式除法,把1-255的数映射成2的n次方(0<=n<=255)的伽罗瓦域Galois Field之类的神一样的东西,以及基于这些基础的纠错数学公式,因为我的数据基础差,对于我来说太过复杂,所以我一时半会儿还有点没搞明白,还在学习中,所以,我在这里就不展开说这些东西了。还请大家见谅了。(当然,如果有朋友很明白,也繁请教教我)

最终编码

穿插放置

如果你以为我们可以开始画图,你就错了。二维码的混乱技术还没有玩完,它还要把数据码和纠错码的各个codewords交替放在一起。如何交替呢,规则如下:

对于数据码:把每个块的第一个codewords先拿出来按顺度排列好,然后再取第一块的第二个,如此类推。如:上述示例中的Data Codewords如下:

块 1 67 85 70 134 87 38 85 194 119 50 6 18 6 103 38  
块 2 246 246 66 7 118 134 242 7 38 86 22 198 199 146 6  
块 3 182 230 247 119 50 7 118 134 87 38 82 6 134 151 50 7
块 4 70 247 118 86 194 6 151 50 16 236 17 236 17 236 17 236

我们先取第一列的:67, 246, 182, 70

然后再取第二列的:67, 246, 182, 70, 85,246,230 ,247

如此类推:67, 246, 182, 70, 85,246,230 ,247 ………  ……… ,38,6,50,17,7,236

对于纠错码,也是一样:

块 1 213 199 11 45 115 247 241 223 229 248 154 117 154 111 86 161 111 39
块 2 87 204 96 60 202 182 124 157 200 134 27 129 209 17 163 163 120 133
块 3 148 116 177 212 76 133 75 242 238 76 195 230 189 10 108 240 192 141
块 4 235 159 5 173 24 147 59 33 106 40 255 172 82 2 131 32 178 236

和数据码取的一样,得到:213,87,148,235,199,204,116,159,…… …… 39,133,141,236

然后,再把这两组放在一起(纠错码放在数据码之后)得到:

67, 246, 182, 70, 85, 246, 230, 247, 70, 66, 247, 118, 134, 7, 119, 86, 87, 118, 50, 194, 38, 134, 7, 6, 85, 242, 118, 151, 194, 7, 134, 50, 119, 38, 87, 16, 50, 86, 38, 236, 6, 22, 82, 17, 18, 198, 6, 236, 6, 199, 134, 17, 103, 146, 151, 236, 38, 6, 50, 17, 7, 236, 213, 87, 148, 235, 199, 204, 116, 159, 11, 96, 177, 5, 45, 60, 212, 173, 115, 202, 76, 24, 247, 182, 133, 147, 241, 124, 75, 59, 223, 157, 242, 33, 229, 200, 238, 106, 248, 134, 76, 40, 154, 27, 195, 255, 117, 129, 230, 172, 154, 209, 189, 82, 111, 17, 10, 2, 86, 163, 108, 131, 161, 163, 240, 32, 111, 120, 192, 178, 39, 133, 141, 236

这就是我们的数据区。

Remainder Bits

最后再加上Reminder Bits,对于某些Version的QR,上面的还不够长度,还要加上Remainder Bits,比如:上述的5Q版的二维码,还要加上7个bits,Remainder Bits加零就好了。关于哪些Version需要多少个Remainder bit,可以参看QR Code Spec的第15页的Table-1的定义表。

画二维码图

Position Detection Pattern

首先,先把Position Detection图案画在三个角上。(无论Version如何,这个图案的尺寸就是这么大)

 

Alignment Pattern

然后,再把Alignment图案画上(无论Version如何,这个图案的尺寸就是这么大)

 

关于Alignment的位置,可以查看QR Code Spec的第81页的Table-E.1的定义表(下表是不完全表格)

 

下图是根据上述表格中的Version8的一个例子(6,24,42)

 

Timing Pattern

接下来是Timing Pattern的线(这个不用多说了)

 

Format Information

再接下来是Formation Information,下图中的蓝色部分。

 

Format Information是一个15个bits的信息,每一个bit的位置如下图所示:(注意图中的Dark Module,那是永远出现的)

 

这15个bits中包括:

  • 5个数据bits:其中,2个bits用于表示使用什么样的Error Correction Level, 3个bits表示使用什么样的Mask
  • 10个纠错bits。主要通过BCH Code来计算

然后15个bits还要与101010000010010做XOR操作。这样就保证不会因为我们选用了00的纠错级别和000的Mask,从而造成全部为白色,这会增加我们的扫描器的图像识别的困难。

下面是一个示例:

 

关于Error Correction Level如下表所示:

 

关于Mask图案如后面的Table 23所示。

Version Information

再接下来是Version Information(版本7以后需要这个编码),下图中的蓝色部分。

 

Version Information一共是18个bits,其中包括6个bits的版本号以及12个bits的纠错码,下面是一个示例:

 

而其填充位置如下:

 

数据和数据纠错码

然后是填接我们的最终编码,最终编码的填充方式如下:从左下角开始沿着红线填我们的各个bits,1是黑色,0是白色。如果遇到了上面的非数据区,则绕开或跳过。

 

掩码图案

这样下来,我们的图就填好了,但是,也许那些点并不均衡,如果出现大面积的空白或黑块,会告诉我们扫描识别的困难。所以,我们还要做Masking操作(靠,还嫌不复杂)QR的Spec中说了,QR有8个Mask你可以使用,如下所示:其中,各个mask的公式在各个图下面。所谓mask,说白了,就是和上面生成的图做XOR操作。Mask只会和数据区进行XOR,不会影响功能区。(注:选择一个合适的Mask也是有算法的

 

其Mask的标识码如下所示:(其中的i,j分别对应于上图的x,y)

 

下面是Mask后的一些样子,我们可以看到被某些Mask XOR了的数据变得比较零散了。

 

Mask过后的二维码就成最终的图了。

好了,大家可以去尝试去写一下QR的编码程序,当然,你可以用网上找个Reed Soloman的纠错算法的库,或是看看别人的源代码是怎么实现这个繁锁的编码。

(全文完)

38月/121

Google Analytics跨域跟踪原理分析与设置-[跟踪代码设置]

发布在 邵珠庆

 

自定义域跟踪可用于多种情况:

  • 子域 - 跟踪访问过 dogs.example.com 和 www.example.com 这两个网站的所有访问者,两者的数据将显示在同一个报告配置文件中
  • 子目录 - 只跟踪访问了某个子目录(如 www.example.com/dogs)的访问者,其数据将单独显示在一份报告中,就像它是一个单独的网站一样
  • 顶级域 - 跟踪对您拥有的两个域(如 www.example.com 和 www.example2.com)进行访问的所有访问者,两者的数据将显示在同一个报告配置文件中
  • IFrame 的内容 - 跟踪另一个域的 iFrame 中的内容的访问者和浏览量数据。

部署实现要点,请严格按照实验步骤实现:

前两点:注意push方法的顺序;_setDomainName设置

  _gaq.push(['_setAccount', 'UA-XXX-1']);

  _gaq.push(['_setDomainName', '.XXX.cn']);//(请设置在各自跨域的根域下)

  _gaq.push(['_setAllowLinker', true]);

  _gaq.push(['_setAllowHash', false]);

  _gaq.push(['_trackPageview']);//(请放在后面,否则会重新刷新Cookie)

后两点:传递链接href与_link要是同一个URL;要写return false

<a href="http://abc.shaozhuqing.com/abc.html" onclick="_gaq.push(['_link', ' http://abc.shaozhuqing.com/abc.html']); return false;">_link(get) View My OTA fengshun</a>

辅助工具插件:

Firebug查看Cookie的变化和_utm.gif参数的专递

Omnibug 监控服务器发送请求情况

默认情况下,Google Analytics为每个独立域名(包括主域名下的子域名)创建单独的数据报告(包括访问者信息、流量来源等),两个域名网站间的任何链接将被归为引荐流量。因此,如果要实现同时跨域跟踪主域名与子域名、单独跟踪网站的某个子目录、同时跨域跟踪两个主域名、跟踪iFrame嵌入的域名内容等,就需要对Google Analytics基础跟踪代码进行自定义,以实现跨域跟踪。本文将介绍Google Analytics跨域跟踪的设置,以及和大家一起探讨跨域跟踪的原理。

Google Analytics跨域跟踪代码设置:跨域跟踪主域名及其子域名、跨域跟踪两个主域名、 跨域跟踪主域名与另一主域名的子目录 、 跨iFrame跟踪 、 跟踪单个子目录 、 跨主域名跟踪其两个或多个子目录

跨域跟踪原理说明

默认情况,Google Analytics通过读取网页托管的 document.domain 属性,获取网站的域名(主域名、子域名),然后为其设置/读取 Cookie,并最终生成该域名的数据。

Google Analytics跨域跟踪Cookie主域名与域哈希值

图一:Google Analytics跨域跟踪Cookie主域名与域哈希值

因此,可以通过控制各域名间(主域名与主域名之间、主域名与子域名之间)的Cookie共享,将各域名的访问数据记录到同一个域名Cookie上,实现主域名之间、主域名与子域名之间的访客数据共享,即跨域跟踪。

跨域跟踪设置成功后,通过查看浏览器访问Cookie中Google Analytics跟踪参数_utma,你会发现各个域名下的Cookie有相同的部分,例如跨域跟踪主域名与其二级域名设置后,Cookie中_utma都属于共同一个域名,例如.exmaple.com,且其域哈希值为1。

同样,可以通过限制Cookie共享,实现Google Analytics跟踪单个子目录。

Google Anlaytics跨域跟踪主域名及其子域名

图二:Google Anlaytics跨域跟踪主域名及其子域名

跨域跟踪主域名及其子域名

通常,规模较大的网站会考虑为每个大分类、项目、购物车等在主域名下创建一个独立子域名,例如:

* www.example-.com

* news.example.com

* cart.example.com

对于此类情况,你需要对主域名与子域名的所有跟踪代码使用以下的自定义设置。

<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-1']);
_gaq.push(['_setDomainName', '.example.com']);
_gaq.push(['_setAllowHash', false]);
_gaq.push(['_trackPageview']);

 

(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>

说明:_setAllowHash(bool),此方法主要用于设置“允许域哈希”,当设置为true(默认值)时Google Analytics会为每个域名设置一个哈希值,并以此来辨别访客Cookie的完整性,此时访客Cookie将拒绝接收另外域名的访问数据;设置为false将停用域哈希功能(此时域哈希值为1),可进行Cookie数据共享。

Google Analytics跨域跟踪两个不同的主域名

图三:Google Analytics跨域跟踪两个不同的主域名

_setDomainName(DomainName),为Cookie设置域名,跨域跟踪时设置为:前导向“.”主域名,设置前导向“.”主要便于更深层级子域名的跨域跟踪,例如跨域跟踪二级子域名下的三级子域名a.news.example.com。

通过将各域名所有跟踪代码,设置为以上自定义跟踪,即可实现跨域跟踪主域名及其多级子域名。

跨域跟踪两个主域名

若要同时跟踪两个不同的主域名(例如网店www.store.com与购物车www.carts.com),可以做一下跟踪代码自定义。

主域名www.store.com中设置的跟踪代码

<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-1']);
_gaq.push(['_setAllowLinker', true]);
_gaq.push(['_setDomainName', '.store.com']);
_gaq.push(['_setAllowHash', false]);

(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>

同时,需要给www.store.com中跳转到www.carts.com的链接以及数据表单添加跟踪代码,以传递Cookie共享数据:

<a href="www.carts.com"
onclick="_gaq.push(['_link', 'www.carts.com']); return false;">View My Carts</a>
<form name="f" method="post" onsubmit="_gaq.push(['_linkByPost', this]);">

主域名www.carts.com的跟踪代码为:

<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-1']);
_gaq.push(['_setAllowLinker', true]);
_gaq.push(['_setDomainName', '.carts.com']);
_gaq.push(['_setAllowHash', false]);

(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>

同时,传递链接以及数据表单Cookie共享数据:

<a href="www.store.com"
onclick="_gaq.push(['_link', 'www.store.com']); return false;">View My Store</a>
<form name="f" method="post" onsubmit="_gaq.push(['_linkByPost', this]);">

说明:_setAllowLinker(bool),true启用跨域跟踪,并允许通过链接、表单在地址参数中传输Cookie数据,默认为flase;_link()、_linkByPost()分别用于跨域跟踪中链接、表单的Cookie数据传输。

跨域跟踪主域名与另一主域名的子目录

如果想跨域跟踪跟踪一个网站(www.example.com)以及在一另个域名目录下的内容(例如博客、购物车等,www.other.com/myblog),那么可以采用以下跟踪代码(请自行修改UA-XXXXX-1、.example.com):

主域名www.example.com中设置的跟踪代码

<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-1']);
_gaq.push(['_setAllowLinker', true]);
_gaq.push(['_setDomainName', '.example.com']);
_gaq.push(['_setAllowHash', false]);

 

(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>

同时,需要给www.example.com中跳转到www.other.com/myblog的链接以及数据表单添加跟踪代码,以传递Cookie共享数据:

<a href="www.other.com/myblog"
onclick="_gaq.push(['_link', 'www.other.com/myblog']); return false;">View My Blog</a>
<form name="f" method="post" onsubmit="_gaq.push(['_linkByPost', this]);">

另一主域名的子目录跟踪代码为:

<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-1']);
_gaq.push(['_setDomainName', 'none']);
_gaq.push(['_setAllowLinker', true]);

 

(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>

同样需要给跳转到www.example.com的链接与数据表单,添加跟踪代码:

<a href="www.example.com"
onclick="_gaq.push(['_link', 'www.example.com']); return false;">View My Site</a>
<form name="f" method="post" onsubmit="_gaq.push(['_linkByPost', this]);">
Google Analytics跨iFrame跟踪

图四:Google Analytics跨iFrame跟踪

由于二者没有共同的主域名,因此需要将www.other.com/myblog中的_setDomainName设置为none,并通过给链接、表单添加代码传送Cookie共享数据。

跨iFrame跟踪

若想同时跟踪网站(例如www.example.com)以及通过iFrame嵌入的另一个网站(例如www. iframecontent.com)间的访客信息、广告些列信息等,需要已设置跨域跟踪两个域名的跟踪代码后,使用在www.example.com中(iframe嵌入的当前页)使用_getLinkerUrl() 方法传输共享Cookie数据。

_gaq.push(function() {
var pageTracker = _gat._getTrackerByName();
var iframe = document.getElementById('myIFrame');
iframe.src = pageTracker._getLinkerUrl('http://www. iframecontent.com/');
});

说明:_getLinkerUrl(targetUrl, useHash) ,用于跨域跟踪主域名与iFrame(或者在新窗口中打开的外部网站链接)时的网址参数传递Cookie共享数据。

跟踪单个子目录

如果你的网站字子目录没有采用子域名形式,内容又很多或者是单个独立项目(例如www.example.com/myblog/),想单独跟踪,那么可以在该子目录下采取以下跟踪代码:

<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-1']);
_gaq.push(['_setCookiePath', '/myblog/']);
_gaq.push(['_trackPageview']);

 

(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>

说明:_setCookiePath(newCookiePath),为您的网站设置新的 Cookie 路径。默认Cookie路径为主域名的根级路径(/),通过它可以设置Google Analytics所有跟踪的默认路径,从而限制跟踪,实现跟踪单个子目录。

此时,Google Analytics会将/myblog/下的页面当做一个独立的域名站点对待,有独立的访客信息与广告系列信息。
 

65月/100

网站后台万能密码’or’=’or’ 原理

发布在 邵珠庆

很多菜鸟都不知道'or'='or' 为什么可以直接进网站的后台,下面就来解释下给大家吧! 原理是这样的:(以下全部以asp为例子) 很多网站把密码放到数据库中,在登陆验证中一般都用以下sql查询语句去查找数据库, sql=select * from user where username='username'
  很多菜鸟都不知道'or'='or' 为什么可以直接进网站的后台,下面就来解释下给大家吧!
原理是这样的:(以下全部以asp为例子)
很多网站把密码放到数据库中,在登陆验证中一般都用以下sql查询语句去查找数据库,
sql="select * from user where username='"&username&"'and pass='"& pass&'" ,
如果用户提交的用户名密码和数据库里面的一样就让你登录,反之则不行。
这里多嘴两句,or 是一个逻辑运算符,作用是在判断两个条件的时候,只要其中一个条件成立,那么
等式将会成立.而在语言中,是以1来代表真的(成立).那么在这行语句中,原语句的"and"验证将不再
继续,而因为"1=1"和"or"令语句返回为真值.。(其实也好理解,英文or是或者的意思,也就是说
这个或者那个中有一个是对的,那么整句话就对的,那我还管你后面的and甘什么呢?)好了,
我们根据sql这个特性构造一个特殊的用户名和密码来绕过它的验证,就用我构造的那个'or' '=' ,
用户名和密码都是'or' '=',我们来看看放到整个程序中会是什么样子。
sql="select * from user where username=''or' '=''and pass=''or' '='' (注意,or前面和=后面都不是
双引号,而是两个单引号,查询语句里面没有双引号,双引号只是让里面的变量变成字符而已,
我们查询的时候双引号中的变量就被我们提交的数据所代替),好了,现在整句话的意思是:从数
据库的user表中查找的用户名是空(两个单引号之间没东西当然是空了:))或者空等于空。废
话,因为空当然等于空了,所以程序就认为你提交的数据是合法的,于是就放你通过拉and后面
的密码验证都不要了。
有人问我,是不是只有这个'or' '=' 才可以绕过验证呢? NO,you are wrong !
根据这个原理我就可以随便构造我喜欢的语句,比如 aweige' or 'aweige'<>'骆驼
这样放进去就变成了用户名是aweige或者aweige不等于骆驼,废话,aweige当然不不等于骆驼拉
难道还等于骆驼啊??于是就给我放行了。大家也可以根据自己的喜欢去构造这样的语句,我就
不多说了。我想说的是修补方法。

修补方法有两(当然还有别的,这只是我自己常用的):
1,对输入的内容验证
可以加一些脚本来验证客户端输入的内容进行验证
2,特殊字符特别是单引号的过滤。
我们也看到了,上面的构造语句中,都有但引号的存在,也有一些其它的字符,因此,只要我们
把这些东西都过滤掉,系统就会安全一点了。
可以用replace语句对但引号和其他特殊字符进行过滤,比如
replace(username,"'","''") '把单引号转换为两个单引号
replace(username,"<>"," ") '把不等号转换为空
这样的话用户提交的构造语句就没用了。
========
后记
========

1,以上的漏洞只是登录的问题,如果再精心构造,还能得到整个系统的全部数据,我曾用过自
己构造的union语句拿到金梅电影的所有钻石会员和黄金会员,搞得我电影都看不完,大家去仔细
研究学习一下asp和sql数据库查询语言的话可能还会得到比我还多的东西哦
2,现在的系统除了一些比较烂的之外,基本上都已经修补好了这个漏洞,所以,远离知道了,
大家就去学习新的东西,通过别的方法来得到我们想要的东西。

43月/100

PHP小偷程序原理、实例及改进

发布在 邵珠庆

优点:通过PHP小偷,我们可以借用别人网站上的信息而不用自己辛苦地去采集。
缺点:需要把整页的HTML代码读取到本地,然后通过匹配获取到想要的信息再进行显示,这样大大影响网页的加载速度。
改进:通过AJAX异步读取HTML代码,后台进行匹配获取到想要的信息,再显示到前台页面。
预备知识:PHP、AJAX、正则表达式。
关键字:file_get_contents()、fopen()、fwrite()、eregi(),前三个关键字都是关于PHP文件处理的函数,eregi()是关于正则表达式的函数。

一、PHP小偷原理的实现:

1、file_get_contents()、fopen()、fwrite()的应用

咱们用华夏黑客牛刀小试吧,把主页的全部信息获取过来。

建立一个PHP文件:
<?php
$url='http://www.77169.com';
//file_get_contents()函数获取网页的html文档
$file=file_get_contents($url);
//建立一个新文件ImitationIndex.htm
$newfile=fopen('ImitationIndex.htm','w');
//把内容读取进去
fwrite($newfile,$file);
//关闭打开的文件
fclose($newfile);
?>

ImitationIndex.htm获取主页全部的HTML(保存好,以备下次使用)。

2、eregi()函数的应用

通过eregi()获取里的内容:
<?php
$url='http://www.77169.com';
//file_get_contents()函数获取网页的html文档
$file=file_get_contents($url);
//通过eregi()匹配获取想要的信息
eregi('<title>(.*)</title>',$file,$rg);
//建立一个新文件
$newfile=fopen('title.htm','w');
//把内容读取进去
fwrite($newfile,$rg[1]);
?>

打开title.htm可以看到已经获取了<title></title>之间的内容

从上面的两个例子,已经知道PHP小偷的实现原理,从中也知道它的不足之处,但通过AJAX可以完善它,使它可以用于实践项目中。

二、PHP小偷技术的实用和改进:

目的:获取华夏黑客的最新资讯,并实时更新查看示例。

实际中可能只用到三个页面:showNews.php、Update.php、HackNews.htm,但为了能看到实时更新的效果,这里用到了模拟主页的页面ImitationIndex.htm。

showNews.php:
<style type="text/css">
body{background:#c60;}
a{color:#444;font:12px Courier New;padding:8px;}
a:hover{color:#f00}
#hei_content{width:400px;background:#ccc;border:2px solid #000;border-bottom:5px solid #000;}
</style>
<?php
echo('<div id="hei_content">');
include('HackNews.htm');
echo('</div>');
?>
<script type="text/javascript">
window.onload=UpdateNews;
function GetXmlHttp()
{
var xmlhttp;
try
{
//IE7.0 ect
xmlhttp=new ActiveXObject("Msxml2.XMLHTTP");
}
catch(a)
{
try
{
//ie6.0 ect
xmlhttp=new ActiveXObject("Mscrosoft.XMLHTTP");
}
catch(b)
{
//非IE
xmlhttp=new XMLHttpRequest();
}
}
return xmlhttp;
}
function StateChange()
{
if(xmlhttp.readyState==4&&xmlhttp.status==200)
{
document.getElementById("hei_content").innerHTML=xmlhttp.responseText;
}
}
function UpdateNews()
{
xmlhttp=GetXmlHttp();
xmlhttp.onreadystatechange=StateChange;
var url='Update.php';
url=url+"?sid="+Math.random();
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
</script>

HackNews.htm是已经缓存的文件,这样不用加载主页上的整个HTML再显示,这个工作留给AJAX:
document.getElementById("hei_content").innerHTML=xmlhttp.responseText

xmlhttp.responseText就是加载更新后的内容。

Update.php:
<?php
$url='ImitationIndex.htm';
//file_get_contents()函数获取网页的html文档
$file=file_get_contents($url);
//$regx为正则表达式的内容,用于匹配获取想要的信息
$regx='<td background=http://hack.77169.com/UploadFiles_8057/200902/20090220100422648.gif colSpan=3 height=100>
(.*)</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colSpan=3><IMG height=8 src=/"http://hack.77169.com/UploadFiles_8057/200902/20090220100422568.gif';
//eregi()获取匹配到的内容,赋值给数组变量$rg;
eregi($regx,$file,$rg);
//建立一个新文件HackNews.htm
$newfile=fopen('HackNews.htm','w');
//把内容读取进去
fwrite($newfile,$rg[1]);
fclose($newfile);
//用iconv编码转换后,输出匹配的HTML内容
$rg[1]=iconv('gb2312','utf-8',$rg[1]);
echo($rg[1]);
?>
Update.php是异步更新的后台页面,“$newfile=fopen('HackNews.htm','w');”和“fwrite($newfile,$rg[1]);”把更新的内容重新保存在HackNews.htm中,下次在index.php中include时就直接调用这个页面,“$url='ImitationIndex.htm'”在实际应用中应该是“$url='http://www.77169.com'”,但为了便于调试,建立一个ImitationIndex.htm模拟页面,如果对ImitationIndex.htm页面中最新资讯中的内容改改,就可以看到实时更新效果。

总结:通过AJAX改进的PHP小偷技术,在采集多个网站的大量信息下,页面的加载速度并不会受多大影响。