0

0

基于Java的开源URL嗅探器的图文代码分享

黄舟

黄舟

发布时间:2017-03-25 11:03:12

|

2527人浏览过

|

来源于php中文网

原创

这是一个可以检测并规范化文本中的url地址的java库。

1280.png

今天,我们很高兴做一个分享,因为我所在的 Linkedin 公司 开源了我们做的一个ULR探测工具:URL-Detector  Java 库。

Linkedin 在每一秒钟,会检查数十万数量级的 URLs 。这些 URL 可能是来自恶意软件或者钓鱼网站的,为了保障我们每一个用户有一个安全的浏览体验,同时防止潜在的危险,我们后端的内容检查服务程序会检查所有由用户产生的内容。为了在这每秒数十万规模的用户内容上检测不良的 URL,我们要有能够在快速此规模上提取文本中URL 的方法。

我们的服务器中的 URL地址有两种形式:

立即学习Java免费学习笔记(深入)”;

  • 一种是单一的 URL

  • 一种是在一大块的文本内容中

如果发送过来的是单一的 URL,我们可以通过我们的内容检查服务直接验证;

如果发送过来的是大块的文本内容,我们会先通过我们的URL探测器 ,经过搜索算法来验证这个文本是否有潜在危险的URL地址;

在我介绍URL探测器是如何工作的和它所能提供给的功能之前,让我们先来了解一下我们做这个项目的动机。

我们的目标是:检测出尽可能多的恶意链接,但是我们不希望紧紧局限于检测在 RFC 1738 中定义的URL地址,而是希望可以检测出任何能够在真正的浏览器地址栏中输入并且可以访问到的URL地址。因为,一个浏览器的地址栏中对 URL 的定义比起 在 RFC 1738 定义的来说,是非常松散的。同时,很多浏览器有不同的行为,所以,我们要找到一种URL文本规则能够被大部分流行的浏览器解析,它不是像RFC中定义语法那样简单。

最初,我们开始第一种解决方案,基于正则表达式。它可以帮我们检测到许多潜在的网址,其中有不少却是真的有潜在危险的,但是其中也有不少是没有的,而且有许多有危险的地址被遗漏了。用这种方式,为了抓取更多的地址这是一个反复匹配的过程,这可能出现一些不状况,比如,一个简单URL匹配的正则:

Regex:
(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?

然后,如果你想检测到不包含 scheme 的 URL,对应修改正则如下,这是其中一个的例子说明浏览器的地址栏可以解析的地址,但是却不符合 RFC 规范。

Regex:
((ftp|http|https):\/\/)?(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?

经过各种浏览器和多场景的兼容,我们终于得到最后的正则:

Regex:
((((f|ht)tps?:)?//)?([a-zA-Z0-9!#$%&'*+-/=?^_`{|}~]+(:[^ @:]+)?@)?((([a-zA-Z0-9\\-]{1,255}|xn--
[a-zA-Z0-9\\-]+)\\.)+(xn--[a-zA-Z0-9\\-]+|[a-zA-Z]{2,6}|\\d{1,3})|localhost|(%[0-9a-fA-F]{2})+|[0-9]+)
(:[0-9]{1,5})?([/\\?][^ \\s/]*)*)

正如你所看到的,每一个兼容或者一个新的场景带来的小的逻辑分支,就对应至少增加几个字符的正则表达式长度。你可以在 这里 看到这种情况究竟有多复杂(注意:一些类似的 URL 匹配的的正则表达式 长度竟然超过了5500字符)。我们发现许多通过这种方式检测到的 URL 虽然是科学的 ,但是却也给我们带来了困扰。因为,我们越是频繁的变动正则,我们发现会有对应更多的误报 URL 。我们要是不优化这些正则,我们就发现我们遗漏的 URL 还很多。

因为我们发现太多的错误的匹配,我们采取了减少匹配数量的方法。编辑原始的复杂的正则表达式语句让我们引入了更多错误。因此,我们需要多正则表达式。下面的例子是我们其中一个正则表达式,用来排除“localhost”和“由数字和点组成的IPv4地址”。

Blacklisted Regex: ^((\\d+(\\.\\d+){0,2})|(\\d+(\\.\\d+){4,})|localhost)$

这样做的结果是,当解析大文本的时候,将耗费很长的时间,有些一次解析甚至是秒级别的。但是,我们的需要每秒处理数十万数量级的的 URL,这么耗时的这个方案明显是不可行的。同时,我们还发现正则表达式有一个缺点,就是:匹配易,处理分析难、维护难。就这样,我们的 URL探测器诞生了。

为了取代使用正则表达式,我们手工打造了一个有限状态机来解析出在文本中的URL。 有限状态机(你可以在这里了解更多信息)是由一组状态组成,状态之间可以由输入事件来触发状态转换。在这种请求下,输入事件就是我们在文本中正在解析的字符。

这个有限状态机有几个状态,主要是基于 URL 的各部分拆分的。状态由一系列的布尔变量保持,每一次一次消耗一个字符,同时进行一次状态转移。为了性能考虑,这个有限状态机器被设计成这样的逻辑拓扑顺序,没有箭头会从后面的状态指向前面的状态。举个例子,如果你在 host 后面检测到 “/”,那么状态机就不会再跟踪的 scheme ,因为它是点头过去的一端。如果状态机在任何一个位置撞到一个非预期的字符,它将返回上一次最新的结束状态,同时重新开始这个算法。

这个最棘手的部分是匹配字符。这些字符实际上,有可能在多个状态中存在。举个例子,比如冒号 “ : ”,它可以出现在至少三个地方:在 scheme 后面,在username 和 password 中间,或者是在 host 和 port 中间,并且,当我们处理IPv6的时候,它变的更加复杂,因为IPv6的地址也可以包括冒号的。但是,状态回溯主要是发生在一些奇怪的情况下,比如一个文本包含一系列非空白字符其中又包含多个冒号,而相比之下,正则表达式状态回溯会更加频繁。所以,我们的状态机的平均运行时间有显著的改善:

以下是一些关于性能提升的统计数据( 正则表达式 VS URL的探测器 ):

关于这个库的功能:

它是能够找到并检测任何网址,如:

  • HTML 5 Scheme – //www.linkedin

    魔法映像企业网站管理系统
    魔法映像企业网站管理系统

    技术上面应用了三层结构,AJAX框架,URL重写等基础的开发。并用了动软的代码生成器及数据访问类,加进了一些自己用到的小功能,算是整理了一些自己的操作类。系统设计上面说不出用什么模式,大体设计是后台分两级分类,设置好一级之后,再设置二级并选择栏目类型,如内容,列表,上传文件,新窗口等。这样就可以生成无限多个二级分类,也就是网站栏目。对于扩展性来说,如果有新的需求可以直接加一个栏目类型并新加功能操作

    下载

    .com

  • 用户名  -用户:pass@linkedi

    n.com

  • 电子邮件  - fred@linkedi

    n.com

  • IPv4地址  – 192.168.1.1/hello.html

  • IPv4的八位字节  – 0×00.0×00.0×00.0x00IPv4的十进制  – HTTP:// 123 123 123 123 /

  • IPv6地址的  – FTP:// [:] /你好

  • IPv4映射的IPv6地址  – [fe30:4:3:0:192.3.2.1]/

另一个令人兴奋的是,它也能识别已经被识别过的URL的部分。例如,对于 URL:user@example.com:39000/hello?boo=ff#frag,它能识别到以下的部分:

  • Scheme – “http”

  • Username – “user”

  • Password – null

  • Host – “example.com”

  • Port – 39000

  • Path – “/hello”

  • Query – “?boo=ff”

  • Fragment – “#frag”

这个库还能够处理引号匹配和HTML。根据你输入的字符串,你可能想以某种特别的方式来处理某些字符。例如你正在解析一段 HTML,你可能想去除引号或者尖括号,比如,你输入的字符串像这样的:

linkedin.com  ,那么你可能想确保引号和尖括号被挑出来。出于这个原因,这个库已经可以通过UrlDetectorOptions 这个 Java 类来设定不同的运作模式, 以改变对你输入的内容的 “探测敏感度” 。通过这种方式,你可以正确的获取到 linkedin.com 而不是linkedin.com 。

使用这个库

想要使用这个库,只需要简单地从 GitHub 仓库上克隆下来,并导入 URL-Detector 库。下面是一个使用的示例:

import com.linkedin.urls.detection.UrlDetector;
   import com.linkedin.urls.detection.UrlDetectorOptions;
   ...
   UrlDetector parser = new UrlDetector("hello this is a url Linkedin.com", UrlDetectorOptions.Default);
    List found = parser.detect();

    for(Url url : found) {
        System.out.println("Scheme: " + url.getScheme());
        System.out.println("Host: " + url.getHost());
        System.out.println("Path: " + url.getPath());
    }

有关更详细的信息,可以到 Readme 里看 “如何使用”这一部分。

致谢

特别感谢 Vlad Shlosberg 和 Yulia Astakhova 对这个库的贡献。

总结

如果大家有对这个库的改进建议,可以通过 GitHub 告诉我们;同时,如果有任何疑问,可以联系我们任何一个,我们将免费帮助你。祝你“探测”愉快!

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

公务员递补名单公布时间 公务员递补要求
公务员递补名单公布时间 公务员递补要求

公务员递补名单公布时间不固定,通常在面试前,由招录单位(如国家知识产权局、海关等)发布,依据是原入围考生放弃资格,会按笔试成绩从高到低递补,递补考生需按公告要求限时确认并提交材料,及时参加面试/体检等后续环节。要求核心是按招录单位公告及时响应、提交材料(确认书、资格复审材料)并准时参加面试。

44

2026.01.15

公务员调剂条件 2026调剂公告时间
公务员调剂条件 2026调剂公告时间

(一)符合拟调剂职位所要求的资格条件。 (二)公共科目笔试成绩同时达到拟调剂职位和原报考职位的合格分数线,且考试类别相同。 拟调剂职位设置了专业科目笔试条件的,专业科目笔试成绩还须同时达到合格分数线,且考试类别相同。 (三)未进入原报考职位面试人员名单。

58

2026.01.15

国考成绩查询入口 国考分数公布时间2026
国考成绩查询入口 国考分数公布时间2026

笔试成绩查询入口已开通,考生可登录国家公务员局中央机关及其直属机构2026年度考试录用公务员专题网站http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/examResult/written_result.html,查询笔试成绩和合格分数线,点击“笔试成绩查询”按钮,凭借身份证及准考证进行查询。

11

2026.01.15

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

65

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

36

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

75

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

21

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

35

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.5万人学习

C# 教程
C# 教程

共94课时 | 6.8万人学习

Java 教程
Java 教程

共578课时 | 46.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号