京东商城Jsonp 漏洞分析 (京东商城XSS漏洞)

继续我们jsonp 安全使用分享吧!上一篇文章我们提到jsonp使用,常见2种类型漏洞出现!详细可以看看:Jsonp常见安全漏洞分析 ,今天我们来结合实例分析下该漏洞的测试、及利用过程吧!

题外话

为什么我选择是京东商城来分析它的jsonp 漏洞呢,其实主要原因最近6.18一直在做活动,我也买了不少便宜东西。现在该商城越做越好了。它系统也非常庞大,速度性能也很好。当时在购物时候,只是想看看,它的系统分离设计方面。通过分析页面http请求,发现有很多jsonp调用(也许跟换域名有关系,2种域名都可以访问,中间用jsonp交换数据),于是就看看,jsonp常见2种安全方面,有没有做处理。结果一测试。发现完全没有做任何处理,几乎是完完全全暴露出来。个人认为,对于这么大站点,这一点还是头一次遇到!居然,没有任何参数处理、以及资源授权!

京东商城Jsonp xss漏洞分析

京东商城xss漏洞

我们看到,该请求就是一个jsonp,

默认返回:jsonp13**********({“Identity”:{“Name”:”",”IsAuthenticated”:false}}),我们知道callback传入参数,会在response中 作为函数调用名称返回!

分析callback 字符范围

1、测试下有没有屏蔽常见特殊字符” <> ()’”;. {}“,以下这些字符,经常会用到xss里面的。

京东商城callback没有屏蔽特殊字符

到这里,分析说明这里存在着xss注入漏洞的。而且,可以选择很多种方法注入! 本编文章,旨在说明jsonp xss漏洞成因!不会具体去扩大漏洞拿到其它什么权限。以下还有个很有意思事情,callback其实,jd对一些特殊字符串做了处理的。我们看看:

image

从上图中,我们可以看到,京东商城,对输入callback对一些特定的字符串进行了屏蔽处理!这也是,我们做xss漏洞检查时候,经常出现问题。屏蔽字符串能够屏蔽完吗?常见26字符,长度不一任意组合。该有多少字符串呢? 很多朋友,在做安全检测时候,就是屏蔽某些觉得很不安全的标签就认为安全了。 其实,我们发现这样做法只能是一时安全,过不了多久,你会发现又有新的字符串出现。你会为此花费大量的人力物力!好了,做类似事情,我们最好方法是,认证那些觉得安全的字符,予以放行!

其实,为什么用白名单方法放行允许的字符呢? 而不是去过滤一些字符串。原因刚刚说了,字符串太多了。过滤不过来!另外是,我们自己每个业务参数,会用到那些字符其实我们更清楚。另外有人会问,为什么不去屏蔽不用的字符呢?我们知道基础ascii码有0-127,128字符。往往我们,不会用到的字符可能更多呢,我们去过滤不会用到字符,有时候更困难!

正确检查jsonp callback方法

建议收到callback函数对它进行白名单字符范围检测!我们可以用一般函数检测规范来检查就可以了。 既然它是一个函数名称,一般都是字符+数字+下划线+点号(对象分割)。那么我们检测变得非常简单,代码类似如:

1
2
3
4
5
6
7
<?php
$callback = isset($_GET['callback'])?$_GET['callback']:'';
 
if(!preg_match("/^[0-9a-zA-Z_.]+$/",$callback))
{
	exit('参数错误!');
}

后记:以上是分析一个jsonp xss漏洞过程。要检测一个站点是否有该漏洞,其实简单方法,就是看通过参数传入进去的特殊字符,是不是原原本本的response 返回出来。 如果有朋友问我,怎么样利用该漏洞,它能做点什么? 你可以把它比作一个蚁穴,能带来多大危害,看蚂蚁怎么样啃食啦!这些年,sql注入几乎难找了,不过xss漏洞是头号杀手。只要有xss漏洞出现,几乎可以做到无所不能,就看利用的人怎么用了。 以上漏洞,我反馈京东商城,这么好的一个网站,不能因为这个小小xss,给用户带来大的安全隐患了!最后,欢迎朋友提出自己建议!还有一个忘记说了,就是它的jsonp访问权限完全没有限制,下次再分享吧!

Posted in web安全 | Tagged | Leave a comment

Jsonp常见安全漏洞分析(京东商城Jsonp 漏洞分析)

JSONPJSON with Padding)是资料格式 JSON 的一种“使用模式”,可以让网页从别的网域要资料。这个解释来自于互联网上面的答案。jsonp只是 一种使用json模式,之所以能够很广泛使用。主要用它来解决跨域访问问题。可以方便跨域名传输数据。一些是一个jsonp的例子。但是,正确的使用jsonp是至关重要的,用得不好。将带来重要资料把超范围访问,还会带来各自xss漏洞。

JSONP跨域请求例子

传统的ajax ,往往是 XMLHttpRequest ,读取一个接口,返回类似: {“Name”: “小明”, “Rank”: 7} json值。一般我们都采用xmlhttprequest方法通过状态判断执行请求是否完毕。

JSONP的使用模式里,该URL回传的是由自定义传入函数名,动态生成JSON作为该函数入参,这就是JSONP 的“填充(padding)”或是“前辍(prefix)”的由来。

请求:

<script type="text/javascript"
         src="http://www.example.com/RetrieveUser?UserId=1823&callback=parseResponse">
     </script>
返回:
parseResponse({"Name": "Cheeso", "Id" : 1823, "Rank": 7})


parseResponse是传入参数值决定的,这样好处通过script标签可以解决跨域问题,并且只要script src地址加载完,js解析引擎就开始执行src地址返回 js内容了。 我们使用者不用关心,什么时候src地址加载解析完。只用写好接收函数:parseResponse,到时候自动回执行该项目。比传统ajax确实多了很多方便!目前,象google翻译,地图等都用该方法。实现了跨域及异步调用!

JSONP漏洞将来自哪里?

它给我们带来的发布,是毫无疑问的。那么它将会有哪些漏洞呢?首先,我们知道,一切输入是有害的。传入callback 值会在结果里面直接返回。因此,如果该参数过滤不严格。可以随便输入:callback值为:alert(‘1’);parseResponse  字符串。返回结果会打印个alert窗口,然后也会正常执行。

那么另外我们知道,flash是可以跨域的。flash请求外部资源,现在都有个”crossdomain.xml”,可以授权允许那些来源的站点,访问指定站点的资源。其实目的就是为了防止,资源被越权调用了。 如果我们不对其授权,那么任何网站都可通过:创建script标记,读取我网站资源了!这个安全项,也就是是否有对访问来源进行了授权访问!

JSONP漏洞总结:

知道了JSONP漏洞点主要有:callback参数注入、资源访问授权设置!我们其实,可以通过这2项,来检测我们的做的JSONP项目,里面是否有安全隐患了。好了,今天先分析到这里。这些漏洞都是,技术实现型漏洞!只要,我们明白了方法,杜绝是很容易的。之所以会出现类似安全隐患,更多来自,不知道这里有类似安全问题! 题外话、发发感慨!!现在网上看到很多教程,以及书籍都只会讲,怎么样使用某个功能,它的方法、技巧等等!很少解决,技术功能点安全避免漏洞的调用方法!做一个功能很重要,但是我始终认为,开发一个安全、稳定功能是最基础的前提。 如果做的功能不安全,稳定!它急着上线,只会带来更大的风险、或是损失!!!   欢迎大家交流,提出更换的建议!(”什么?这里不是说京东商城有JSONP漏洞吗?“  ”对!没错!” 今天我这里分析漏洞点,大家可以找找京东商城这方面使用漏洞,我们下次分享实例!)

Posted in web安全 | Tagged | Leave a comment

web开发人员 提升技术、突破瓶颈方法探讨

技术瓶颈表现

作为一名web技术开发人员,也是我们说的IT人员。 刚刚入门时候,会发现有很强的兴趣。天天会遇到新的事情,可以不断做一些新的功能。到后来,会发现。自己所做的工作,技术点都差不多,然后感觉学习东西越来越少。最后,也慢慢对该行业兴趣不强烈了。 而后,慢慢有些油了。 总是感觉学习知识是在炒旧饭,很久也没有感觉到自己的提升。 这个时候,也就是我们经常说的技术瓶颈。

怎么样突破技术瓶颈

我们知道,行行出状元。并且能熟能生巧,那么我们做技术是不是做的多,也自然而然会成为状元,会生巧呢? 确实,作为web技术人员,做得多,对自己编码速度,处理问题提升会很多。 但是,却又不完全成正比。我们发现很多时候,看似我们做系统技术点工作,但是很少有相同产品。只是技术实现类似而已!作为技术人员,我想主要提升方面是:技术广度、另外是技术深度

技术广度,可以从web人员,学习技能入手。可以看看,前面一篇文章:web前端开发人员技能点汇总、技术详细列表  ,这一般很容易理解,也很容易学习到。基本上是这些功能点而已。 但是,另外技术深度,就很难把握!它像水面有张力一样,一般很难沉下去。这里,我们可以想象下,为什么会这样。

技术深度非常重要。作为一名web开发人员,很多都是通过培训,或者自己感兴趣,然后看看书,去模仿模仿,有人指导下。 然后就是一名web人员了。 但是,所有经验大多数来自实际总结,但是,实际我们缺少了,web开发原理东西。这方面一般很少有朋友喜欢整本整本书看。一般习惯网上看看,别人分享经验技巧。这样一来,对学习只是也是很零碎的。这些都是导致想深入学习的原因。

要深入,我们必须对一个问题,首先是了解它是什么,然后是怎么样使用,最后是为什么它会达到这样结果。也就是我们常说的,刨根问底!很多时候,web人员,喜欢”功能开发完了,就OK了”, 也不会去寻找该功能实现本质,有没有其它更好方法。这样,你将始终停留在使用功能。不停重复使用相同功能。 其实,有人说要做好一名技术人员,必须有所追求 其实就是需要有刨根问底的精神。要能每次做同一个事情,都有新要求。我的代码结构,性能、安全、扩展性等方面。是不是提升了。这些都可以是具体提升的一些方面。

因此,要提升自己技术深度方法。就是,每次再实现一个方法方面,有所创新,有所改进。无论是结构,还是性能,还是安全,还是其它等等方面。你会发现,在改造同时,自己对该项知识掌握就自然深入了。 越来越了解该项技能本质了。 做一个有技术追求的人,是能很好的提升自己的广度、深度的!

好了,以上是我对技术成长方面,广度、深度理解。欢迎朋友有不同方法,可以给予建议!

Posted in 学习心得 | Tagged | Leave a comment

正则表达式、分组、子匹配(子模式)、非捕获子匹配(子模式)

前面我们知道正则表达式有很多元字符表示匹配次数(量词),都是可以重复匹配前面出现的单个字符次数。有时候,我们可能需要匹配一组多个字符一起出现的次数。这个时候,我们需要分组了。就是用小括号来括起这些字符,指定子表达式(也叫做分组)。然后你就可以指定这个子表达式的重复次数了,你也可以对子表达式进行其它一些操作。这个时候,可以把括号中一组字符,看作一个整体了。

分组模式举例说明

如:查找字符串中,连续出现多个win字符串的字符。可以这样完成
 
1
2
3
4
5
6
7
<?php
 
$str = "this is win winwindows!";
 
preg_match_all("/(win)+/",$str,$marr);
 
var_dump($marr);

 

正则表达式分组

不用分组模式,同时匹配多个字符,可以吗? 我们发现以前操作符号:[win]+,尽管可以匹配到winwin字符,因为它代表是有w,i,n组合的一个或者多个字符,不会限制顺序。所见它会匹配到象:wwin,www,inw等等,只要是这3个字符组成的,多个字符都匹配成功了。

上面怎么匹配到,每一个有2个结果呢?这就是子模式(子匹配),默认除了可以将多个字符组合一个整体,另外还会把括号,括起来的这部分表达式存储到一个临时缓冲区中,以便后面正则表达式调用。上面这个例子里面,我们不需要,后期调用的。因此,怎么样屏蔽掉这个子表达式捕获内容呢? 只需要在:前加上”?:” 即可。我们看看下面例子正则表达式 分组非捕获模式

正则表达式 分组非捕获模式
 

非捕获模式优点有哪些呢? 从上面看,可以减少捕获,也就会减少匹配次数。因此,在不必要分组表达式加入非捕获前缀”?:”,可以节省内存开销,并且可以提升匹配速度!

刚刚说到了正则表达式分组,默认情况会将子表达式捕获内容,存储到一个缓存区。以便后续调用。 那这个是什么样情况呢?其实,这个是正则表达式的引用。所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容按顺序存储。存储子匹配的缓冲区编号从1开始,最多可以一般存储为9。以便后面表达式引用该值,又叫后向引用。

我们看下下面例子,查找一个字符串中,互不相邻,出现多次系统单词:add。
1
2
3
4
5
6
<?php
$str = "add123456addasdf";
 
preg_match_all('/(add)\d+\1/',$str,$marr);
 
var_dump($marr);

 

正则表达式反向引用

反向引用,常用来处理一些处理一些特殊匹配情况。如:查找字符串中,不相邻重复字符串。查找html一对标签中内容。特别分析html非常常见了(注意,如果使用了反向引用,前面不能屏蔽子匹配捕获,也就是不能加”?:"前缀了)。经常会用:

1
2
3
4
5
6
7
8
9
10
<?php
$str = file_get_contents('http://blog.chacuo.net/');
preg_match_all('/<(\S+)[^>]*>[^<]*<\/\1>/',$str,$marr);
 
var_dump($marr);
 
// (\S+) 表示非显示字符之外所有字符,一般作为html tag名称
// tag格式一般为 <tag   其它属性> 后面[^>]* 匹配tag里面所有其它属性
// 后面的[^<]* 表示 <tag...>中间内容</tag> 表示中间内容,到"<"结束,因此匹配所有[^<]* 字符
// 最后的<\/\1> "\/" 转义"/"字符,后面的"\1" 表示反向应用前面的(\S+)
正则表达式匹配html标签

 

以上是正则表达式使用比较重要的,分组,反向匹配,以及非捕获分组说明及实例。希望对要属性改功能朋友有所帮助。同时欢迎朋友们交流!

Posted in web原理 | Tagged | Leave a comment

web前端开发人员技能点汇总、技术详细列表

常常做了一段时间的web开发,然后就慢慢迷失了方向。感觉自己的技术到一个瓶颈,不知道下一步该要学习哪些知识。常常这个时候,很多人因为瓶颈,导致一直原地踏步!也有写朋友,感觉自己什么都可以了。 记得,我当时刚做1年多网站时候。就有那个感觉,觉得自己什么都可以做了。什么留言板、用户系统、论坛、产品管理等,然后去一家大一点的公司谋职,被一个招聘人员问了几个问题。然后,觉得自己非常自信,回答非常好!但是结果音信全无,指导后来过来几年后,对当时那段时间回忆起来,觉得自己当时勇气可嘉!

下面,这个图,是作为web开发人员,技能知识点汇总。里面常常包括,ui人员、js人员、web编码人员的所有知识点。但是,这3者之间开发中联系密切。彼此之间多了解下,很有必要的!

web开发人员技能知识点汇总
本图来源于开源项目:https://github.com/jacksontian/fks  里面有详细学习资料介绍,大家可以去了解下!
 

从这个图里面,几乎包含了ui,js,web程序开发。这3个方面,无论那个方面人员,我觉得都有必要可以多了解下这些技能点。多了解些技能点,彼此直接沟通会更方便!也将容易得多了。我想,如果很早那年我有看过这个图,我就知道自己有几斤几两啦!(当然,比较早时候,很多知识那个时候还没有出现。不过也至少有这个图里面一半左右知识技能点)

web开发人员技能提升提现

也就是说,怎么样说明自己在进步了,自己确实提高了。我认为有2点重要,上面这个图说的是需要掌握的技能点的广度 ,另外一点就是:掌握技能点的深度 。估计这个时候,我们脑子里面就会想,广度很好理解好验证的。那么深度指的是什么呢,我自己到底掌握到那个深度了呢?下次,我会继续补充!欢迎交流!

Posted in 学习心得 | Tagged | 1 Comment

php header 重定向常出现功能(使用)漏洞

php header函数功能强大,可以给用户发送各种header头信息,只要header头里面能够发送的内容,都可以通过header函数来完成。如发送302跳转,设置cookie,发送401认证,发现last-modify等等! HTTP/1.1 specification for more information on HTTP headers,都可以用该函数完成。总之一句话,任何服务区response应答的头信息几乎都可以用它来发送。如:

response 服务器响应头

这里我们经常用header发送302跳转,会发现一个问题。在走查代码时候,遇到很多同人会有类似操作代码,如:
1
2
3
4
<?php
header("Content-type: text/html; charset=utf-8");
 
//判断用户是否授权
1
2
3
4
5
6
7
if('用户未授权')
{
	header("location:forbidden.php");
}
 
///下面是进行摸个记录操作
//删除条记录,或者修改某条记录……
1
 

这类代码,在开发中很常见,我们会发现,一个没有权限用户,操作该记录,网页会跳转到未授权页面,但是:记录任然被修改了,问题我们找到了,一般操作人员,对于js跳转会知道是前端浏览器跳转的。但是对于php操作跳转,错误认为是服务器跳转,好像php以执行到location,然后就终止了下面运行。 其实,知道header函数真实意义就很容易理解了:header() is used to send a raw HTTP header!

header location 302实际上只是如下:

response 服务器302响应头
跟其它普通echo 函数没有多大区别,只是给header信息头,echo 一行而已。

屏蔽Bug方法:


知道了,发送header跳转,服务器不会终止程序,因此为了安全起见。header locaction后,最好加一句exit()函数。 这样,php解析引擎就会停止解析了!我们正确方法是封装个header_302方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
/*header_302跳转*
 * *
 *@author http://blog.chacuo.net/
 * @param string $url 跳转url
 */
function  header_302($url)
{
	if(headers_sent())
	{
		exit('header 已经发送过!');
	}
	header("location:$url");
	exit();
}

后记:这类问题,不光出在php程序中,其它很多header loction跳转语言程序,原理相同。都有类似功能,很多时候。都是使用时候没有注意,造成的。 容易在代码走查中,遗漏掉!好了,先到这里,欢迎交流!

Posted in web安全 | Tagged , | Leave a comment

正则表达式断言、巡视(Assertions)、正向断言、反向断言

断言(Assertions)在正则表达式概念里面难理解,它通常指的是在目标字符串的当前匹配位置进行的一种测试但这种测试并不占用目标字符串,也即不会移动模式在目标字符串中的当前匹配位置。详细可以看看,正则表达式匹配解析过程探讨分析(正则表达式匹配原理),里面提到“零宽度“很多元字符,只是对特殊位置进行匹配,它们可以理解为断言。

断言元字符

常见断言元字符有:  \b, \B, \A, \Z, \z, ^ ,$ 它们只是表示特殊位置,各自作用如有字符串AB,带位置表示为:0A1B2

元字符 意义(以上面带位置字符串说明)
^ 行首,字符串首 表示位置0
$ 行尾,字符串尾部,表示位置2
\b 字分界线,可以表示:0,2位置
\B 非字分界线,可以表示1位置
\A 目标的开头(独立于多行模式) 表示位置0
\Z 目标的结尾或位于结尾的换行符前(独立于多行模式) 表示位置2
\z 目标的结尾(独立于多行模式)表示位置2
\G 目标中的第一个匹配位置
A,Z,z,G很少使用

这些断言的测试都是一些基于当前位置的测试,断言还支持更多复杂的测试条件。更复杂的断言以子模式方式来表示,它包括先行(前向)断言(Lookahead assertions)和后行(后向)断言(Lookbehind assertions),这些断言判断只做匹配判断条件,不会记录在匹配结果中,不会匹配字符。

先行断言、正向断言、正向巡视(Lookahead assertions)

先行断言,常有表示(?=pattern),从当前匹配位置开始测试后面匹配字符串是否成立,还有(?!pattern)这样两种格式,我们来看看一个例子。源字符串:“abc100”,正则表达式是:
/[a-z]+(?=\d+)/ ,我们分析下过程如下图:

正则表达式先行断言、正向断言、正向巡视

首先由正则表达式字符 [a-z]+ 取得控制权,匹配字符:”abc”,位置从”0”开始匹配,变成3。从该位置测试/d+是否成立。匹配到字符100,返回成立。因此正则表达式正向断言成功。返回匹配字符串”abc”

(?!pattern) 只是,正向匹配,当后面没有匹配成功,将返回真。以下是系统源字符串:abc100,测试结果如下:

正则表达式先行断言、正向断言、正向巡视

 


后行断言、反向断言、反向巡视(Lookbehind assertions)

后行断言,常见表达式是:(?<=pattern)或者(?<!pattern)格式。正则表达式里面,不要出现不固定长度量词,可能会出现死循环。匹配出错。表示当前位置左边将出现匹配字符,则返回真,后面匹配正常。因为如果它出现在最左边,默认位置从0开始,匹配都是失败的。一般都从后面正则表达式开始匹配,再回溯,直到匹配到为止。我们看看下面例子:源字符串:“abc100+=“,正则表达式是:”(?<=\w)\w+”,匹配过程如下图:

正则表达式后行断言、反向断言、反向巡视

 


首先由正则表达式字符 /\w+/取得控制权,匹配字符:”abc100”,位置从”0”开始匹配,匹配到6个字符。从该位置0检测左变\w匹配失败。因此/\w+/从字符b开始匹配到”bc100”,测试它左侧有字符”a”,反向断言正确。因此匹配到字符串“bc100”,(?<!pattern),只是没有匹配成功返回真,其它都一样!

后记:从这篇文章,我们发现搜索特点都是从左到有,一般正向断言放到,正则表达式后,反向断言放到匹配正则表达式前。但是,这里也可以放到前或后。这里就不再举例。欢迎交流讨论!

Posted in web原理, 学习心得 | Tagged | Leave a comment

正则表达式匹配解析过程探讨分析(正则表达式匹配原理)

已经有多篇关于正则表达式介绍的文章,随着我们越来越多使用正则表达式,想对性能做优化、减少我们正则表达式书写匹配Bug。我们不得不进一步深入了解正则表达式执行过程了。下面我们一起学习,分析下正则表达式执行过程。我们会用regexbuddy测试工具分解执行过程,具体工具使用,可以看:正则表达式性能测试工具推荐、优化工具推荐(regexbuddy推荐)。要了解正则表达式解析过程前,我们先来熟悉几个概念。

  • 常见正则表达式引擎

引擎决定了正则表达式匹配方法及内部搜索过程,了解它至关重要的。目前主要流行引擎有:DFA,NFA两种引擎,我们比较区分下。

引擎 区别点
DFA
Deterministic finite automaton
确定型有穷自动机
DFA引擎它们不要求回溯(并因此它们永远不测试相同的字符两次),所以匹配速度快!DFA引擎还可以匹配最长的可能的字符串。不过DFA引擎只包含有限的状态,所以它不能匹配具有反向引用的模式,还不可以捕获子表达式。代表性有:awk,egrep,flex,lex,MySQL,Procmail
NFA
Non-deterministic finite automaton 非确定型有穷自动机,又分为传统NFA,Posix NFA
传统的NFA引擎运行所谓的“贪婪的”匹配回溯算法(longest-leftmost),以指定顺序测试正则表达式的所有可能的扩展并接受第一个匹配项。传统的NFA回溯可以访问完全相同的状态多次,在最坏情况下,它的执行速度可能非常慢,但它支持子匹配。代表性有:GNU Emacs,Java,ergp,less,more,.NET语言,
PCRE library,Perl,PHP,Python,Ruby,sed,vi等,
一般高级语言都采用该模式。

DFA以字符串字符,逐个在正则表达式匹配查找,而NFA以正则表达式为主,在字符串中逐一查找。尽管速度慢,但是对操作者来说更简单,因此应用更广泛!下面所有以NFA引擎举例说明,解析过程!

 

  • 解析引擎眼中的字符串组成

对于字符串“DEF”而言,包括D、E、F三个字符和 0、1、2、3 四个数字位置:0D1E2F3,对于正则表达式而言所有源字符串,都有字符和位置。正则表达式会从0号位置,逐个去匹配的。

  • 占有字符和零宽度

正则表达式匹配过程中,如果子表达式匹配到的是字符内容,而非位置,并被保存到最终的匹配结果中,那么就认为这个子表达式是占有字符的;如果子表达式匹配的仅仅是位置,或者匹配的内容并不保存到最终的匹配结果中,那么就认为这个子表达式是零宽度的。占有字符是互斥的,零宽度是非互斥的。也就是一个字符,同一时间只能由一个子表达式匹配,而一个位置,却可以同时由多个零宽度的子表达式匹配。常见零宽字符有:^,(?=)等

  • 正则表达式匹配过程详解实例

我们掌握了上面几个概念,我们接下来分析下几个常见的解析过程。结合使用软件regexBuddy来分析。

Demo1: 源字符DEF,对应标记是:0D1E2F3,匹配正则表达式是:/DEF/

正则表达式解析过程

过程可以理解为:首先由正则表达式字符 /D/ 取得控制权,从位置0开始匹配,由 /D/ 来匹配“D”,匹配成功,控制权交给字符 /E/ ;由于“D”已被 /D/ 匹配,所以 /E/ 从位置1开始尝试匹配,由 /E/ 来匹配“E”,匹配成功,控制权交给 /F/ ;由 /F/ 来匹配“F”,匹配成功。

Demo2:源字符DEF,对应标记是:0D1E2F3,匹配正则表达式是:/D\w+F/

正则表达式解析过程 

过程可以理解为:首先由正则表达式字符 /D/ 取得控制权,从位置0开始匹配,由 /D/ 来匹配“D”,匹配成功,控制权交给字符 /\w+/ ;由于“D”已被 /D/ 匹配,所以 /\w+/ 从位置1开始尝试匹配,\w+贪婪模式,会记录一个备选状态,默认会匹配最长字符,直接匹配到EF,并且匹配成功,当前位置3了。并且把控制权交给 /F/ ;由 /F/ 匹配失败,\w+匹配会回溯一位,当前位置变成2。并把控制权交个/F/,由/F/匹配字符F成功。因此\w+这里匹配E字符,匹配完成!

Demo3:源字符DEF,对应标记是:0D1E2F3,匹配正则表达式是:/^(?=D)[D-F]+$/

正则表达式解析过程 

过程可以理解为:元字符 /^/ 和 /$/ 匹配的只是位置,顺序环视 /(?=D)/ (匹配当前位置,右边是否有字符“D”字符出现)只进行匹配,并不占有字符,也不将匹配的内容保存到最终的匹配结果,所以都是零宽度的。 首先由元字符 /^/ 取得控制权,从位置0开始匹配, /^/ 匹配的就是开始位置“位置0”,匹配成功,控制权交给顺序环视 /(?=D)/;/(?=D])/ 要求它所在位置右侧必须是字母”D”才能匹配成功,零宽度的子表达式之间是不互斥的,即同一个位置可以同时由多个零宽度子表达式匹配,所以它也是从位置0尝试进行匹配,位置0的右侧是字符“D”,符合要求,匹配成功,控制权交给 /[D-F]+/ ;因为 /(?=D)/ 只进行匹配,并不将匹配到的内容保存到最后结果,并且 /(?=D)/ 匹配成功的位置是位置0,所以 /[D-F]+/ 也是从位置0开始尝试匹配的, /[D-F]+/ 首先尝试匹配“D”,匹配成功,继续尝试匹配,直到匹配完”EF”,这时已经匹配到位置3,位置3的右侧已没有字符,这时会把控制权交给 /$/,元字符 /$/ 从位置3开始尝试匹配,它匹配的是结束位置,也就是“位置3”,匹配成功。此时正则表达式匹配完成,报告匹配成功。匹配结果为“DEF”,开始位置为0,结束位置为3。其中 /^/ 匹配位置0, /(?=D)/ 匹配位置0, /[D-F]+/ 匹配字符串“DEF”, /$/ 匹配位置3。

 

后记:上面这几个例子,我们分析了正则表达式普通匹配,还有回溯过程,然后零宽度字符,匹配过程。当然,给出的例子比较简单,实际过程中会遇到更长,更复杂的正则表达式。但是,思想是类似的。只要我们把我解析原理,都可以逐一分解的。好了,就到这里,欢迎交流!

Posted in web原理 | Tagged | 2 Comments

正则表达式性能测试工具推荐、优化工具推荐(regexbuddy推荐)

前不久,我们推荐了个正则表达式入门学习工具。正则表达式工具推荐(学习工具、测试工具) ,今天我们看下,正则表达式的性能测试工具。这里我们先说下,为什么需要这样的工具,这个工具有什么作用呢?

  • 为什么需要性能测试工具

我们都知道,正则表达式使用进行搜索查找,没有字符串直接查找快!而且性能是几何倍数下降。那么,为什么正则表达式速度会比字符串搜索慢呢。我们来看看,正则表达式查找字符串的匹配过程吧。正则表达式由一些元字符,普通字符,量词字符组合成。默认情况下,这些量词元字符(*,+,?)都是贪婪模式,会最大长度匹配字符串。我们知道,正则表达式往往搜索路径会有多个,我们看看,下面匹配过程。就知道,主要影响正则表达式执行性能有哪些了。

正则表达式匹配过程如:\d+abc,元字符是:”12345bdc”,查找会从左向右进行,\d+,贪婪模式,一下子匹配到12345,然后bdc与\d+不能匹配,”abc”中,”a”字符,开始匹配”bdc”,发现匹配失败。正则表达式开始回溯匹配(贪婪模式量词开始逐一减少匹配字符长度),\d+只匹配”1234”,”5bdc”与”abc”匹配,任然失败。\d+继续减少匹配长度为:”123”,”45bdc”与”abc”匹配,任然失败。继续回退,直到\d+匹配”1”,用”2345bdc”与”bdc”匹配,任然失败。整个匹配就失败了。

从上面过程中,我们发现,每次回溯,要重新操作匹配因此匹配搜索次数,直接影响正则表达式的性能。做正则表达式性能优化,一般就是优化查询的次数。这个是我们分析过程,如果有个工具能够实实在在看到每一步匹配过程,对于我们优化正则表达式将带来太多方便了。这里介绍工具是:regexbuddy软件,它就是一个实实在在看到匹配过程工具。

  • regexbuddy工具怎么样使用,使用介绍

1、安装完regexbuddy

regexbuddy介绍

该工具支持多种程序语言正则表达式,如:perl,pcre,javascript,python,ruby,c#,java等等,还能自动生成程序代码,并且内部带有大量的常用正则表达式。

2、一般切换到side by side:


regexbuddy使用


3、匹配过程


regexbuddy匹配过程


regexbuddy匹配过程

从上面一个匹配看,这个简单一个匹配,搜索了8次,进行了不断查找。如果我们已经准确知道自己要匹配什么样字符,我们可以对源正则表达式修改下,减少匹配次数。就达到优化正则表达式目的,提高匹配效率!

regexbuddy优化正则表达式





后记:这个工具是不是很强大呢,你知道在baidu搜索,该关键字:regexbuddy,就可以方便下载到。通过该工具,对我们写出好的高性能正则表达式确实能带来很大帮助。有时候可能一个小小修改,自己程序正则表达式匹配速度可能几个数量级的提升。好了,欢迎大家交流,你有好的工具、方法,欢迎留言,可以给更多朋友分享!

Posted in web性能, 学习工具 | Tagged | 1 Comment

正则表达式单行、多行模式简介(使用说明)

继上几篇正则表达式相关说明(详情:正则表达式 ),我们今天继续讨论下,它的单行,多行模式使用,及容易出现错误地方。单行,多行模式,都是正则表达式的模式修饰符里面出现的参数。目前常用正则表达式都有该使用选项,如:javascript 正则表达式,一般是:”/正则表达式匹配字符/修饰符“ ,最后一个”/” 后面是修饰符。然后,php也是类似的,c#,python等,一般调用正则表达式的匹配函数,都有一个另外选项的,设置模式。

  • 单行、多行模式容易出现理解错误

为什么说,容易出现理解错误呢,它们英文对应说明是:SingleLine ,MultiLine,刚好是单行、多行意思。因此,很多朋友就会从字面理解里面,得出以下结论:(哈哈、刚刚使用,我也是这些朋友中一员)

1、单行,就是从头到尾匹配,多行就是如果匹配字符串,里面有换行符,就匹配到之前

2、单行跟多行是冲突的,一次只能指定一个选项,不能同时使用

这样来理解其实,很容易就会这样的。我们来看看,官方手册里面怎么说的。

  • 单行、多行模式官方解释

模式符 描述
s(单行) 如果设置了这个修饰符, 模式中的点号元字符匹配所有字符, 包含换行符. 如果没有这个 修饰符, 点号不匹配换行符
m(多行) 目标字符串是由单行字符组成的(然而实际上它可能会包含多行), “行首”元字符(^)仅匹配字符串的开始位置, 而”行末”元字符($)仅匹配字符串末尾。当这个修饰符设置之后, “行首”和”行末”就会匹配目标字符串中任意换行符(\n)之前或之后

 

通过上面说明,其实这2个修饰符都只是,修改正则表达式常见元字符的匹配范围了。如果加”s”修饰符,元字符”.” 将能够匹配换行符(\n),如果加”m”修饰符,元字符”$”,将只匹配到”\n”字符前;元字符”^”,将匹配到”\n”字符后。我们还是举例说明吧!(下面关于正则表达式?字符,可以看看前面一节:正则表达式(regex) 贪婪模式、懒惰模式使用)

  • 举例,看单行应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
///读取hao123.com首页
///并且去掉里面script代码
 
/**
 *去掉script标签*
 * @author chengmo
 * @copyright http://blog.chacuo.net/
 * @param string $content 原字符串 
 * @param int $style 匹配模式
 * @return string
 */
function remove_script($content,$style=1)
{
	$reg = $style == 1?"%<script.*?>.*?</script>%":"%<script.*?>.*?</script>%s";
 
	return preg_replace($reg,"",$content);
}
 
$content = file_get_contents('http://www.hao123.com');
echo remove_script($content);
1
&nbsp;
正则表达式单行匹配模式
正则表达式单行匹配模式
 
 
  • 举例,看多行应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
///读取hao123.com首页
///读取meta标签内容
 
/**
 *读取meta标签内容*
 * @author chengmo
 * @copyright http://blog.chacuo.net/
 * @param string $content 原字符串 
 * @param int $style 匹配模式
 * @return string
 */
function read_meta($content,$style=1)
{
	$reg = $style == 1?"%^<meta.*?/>%":"%^<meta.*?>\s+$%m";	
	preg_match_all($reg,$content,$arr);
	return $arr;
}
 
$content = file_get_contents('http://www.hao123.com');
var_dump(read_meta($content));
正则表达式多行
image
 
 
 
 

后记:s,m 修饰符只对,几个特殊元字符有改变。如果你正则表达式中没有那几个元字符。开启s,m字符前后将没有什么变化的。对于上面读取hao123.com代码,我们可以继续同时使用s,m模式。如:”%<script.*?>.*?(^currentProfile.*$).*?</script>%sm” ,匹配所有script标签,并且里面js代码,有一行以curentProfile开头字符串。(以下是正则表达式,单行多行一起使用)

正则表达式单行多行


							
Posted in web原理 | Tagged | Leave a comment