JavaScript 如何验证 URL
前言
当开发者需要为不同目的以不同形式处理URL时,比如说浏览器历史导航,锚点目标,查询参数等等,我们经常会借助于JavaScript。然而,它的频繁使用促使攻击者利用其漏洞。这种被利用的风险是我们必须在我们的JavaScript应用程序中实现URL验证的原因。
URL验证检查URL是否遵循正确的URL语法,也就是每个URL必须具备的结构。URL验证可以使我们的应用程序免遭基于URL的漏洞,比如恶意脚本注入和服务器端请求伪造(SSRF)。当我们在获取远程资源时没有应用安全编码惯例来验证用户提供的URL时,恶意行为者可以采用SSRF攻击。
URL验证
URL验证的存在是为了加强安全,防止可能存在的漏洞,并消除运行代码时产生的任何错误的机会。但是我们应该在什么时候使用URL验证,在这个过程中我们要验证什么呢?我们应该在所有必须识别和验证诸如网页、图片、gif和视频等资源的软件中实施URL验证。
一个典型的URL包括多个片段,比如协议、域名、主机名、资源名、URL源、端口等等。这些用来告诉浏览器如何追踪指定的资源。我们可以以不同的方式来验证URL:
- 使用正则字面量和构造函数
- URL构造函数
isValidURL
方法- Input元素
- Anchor标签方法
一个典型的URL验证方案接收来自用户的输入,然后对其进行解析,以识别其各个组成部分。验证方案可以确保所有的URL组件符合互联网标准。例如,如果需要,它可以检查URL是否使用安全协议。
主机名验证首先是将主机名分成独立的标签,以确保它们符合顶级域名规范。一个典型的主机名由至少两个用点分隔的标签组成。例如,www.snyk.com 有 "www"、"snyk"和 "com"的标签。每个标签只能由一个字母数字字符或一个连字符组成,无论大小写。然后,验证方案可以确保主机名与URL的允许列表相匹配,以确保只允许指定的URL,并且允许的URL不会被错误地取消资格。
默认情况下,URL中使用的大多数资源的路径都是允许的。然而,端口只能在1到65536的范围内。任何超出这个范围的东西都应该抛出一个错误。我们还可以检查数字IP地址,以判断它是一个IPV4地址还是IPV6地址。
最后,我们也可以检查URL的用户名和密码。这个功能有助于遵守公司政策和凭证保护。
现在,你已经有了这些基础知识,让我们来看看使用javascript的URL验证吧。
如何执行URL验证
在JavaScript中,执行URL验证最简单的方式是使用new URL
构造函数。除此之外,它还得到了Node.js运行时和大多数浏览器的支持。
基本语法如下:
new URL (url)
new URL (url , base)
如果提供相对URL,JavaScript只需要base
元素。如果不提供相对URL,默认为undefined
。另外,如果提供一个具有绝对URL的base
元素,JavaScript会忽略base
元素。
为了验证URL,可以使用以下代码:
function checkUrl (string) {
let givenURL ;
try {
givenURL = new URL (string);
} catch (error) {
console.log ("error is", error);
return false;
}
return true;
}
该函数用于检查URL的有效性。当URL有效时返回true
,否则返回false
。
- 如果你传递
www.urlcheck.com
给该函数会返回false
。因为该参数并不是一个有效的URL。正确版本应该是https://urlcheck.com
。 - 另一个例子是
mailto:John.Doe@example.com
。这是一个有效的URL,但如果移除了冒号,JavaScript就不再认为它是一个URL了。 - 第三个例子是
ftp://
。这不是一个有效URL,因为没有包含主机名。如果你添加两个点(..
),就会变成有效URL。因为点会被认为是一个主机名,也就是说ftp://..
变成了一个有效的URL。
重要的是要记住,非常规的、但完全有效的URL是存在的!它们可能对从事这些工作的开发人员来说是意外的,但在其他方面是完全合适的。例如,以下两个URL都会返回真值:
new URL("youtube://a.b.c.d");
new URL("a://1.2.3.4@1.2.3.4");
这些例子提醒我们,开发者应该依靠URL验证原则,而不是专注于惯例。
如果你想确保有效的URL包含一些特定的URL方案,你可以使用以下函数:
function checkHttpUrl(string) {
let givenURL;
try {
givenURL = new URL(string);
} catch (error) {
console.log("error is",error)
return false;
}
return givenURL.protocol === "http:" || givenURL.protocol === "https:";
}
该函数验证URL,然后检查URL是否使用HTTP或者HTTPS。在这里,ftp://..
会被认为是无效的,因为它不包含HTTP或者HTTPS,而http://..
依旧有效。
使用URL
构造函数的一些其他方式包括:
let m = '<https://snyk.io>';
let a = new URL("/", m);
上述示例使用了base
元素。记录下这个值,我们就可以得到https://snyk.io/
。
要返回一个URL对象而不指定base
参数的话,语法是:
let b = new URL(m);
为了给主机添加一个路径名,我们的代码结构如下:
let d = new URL('/en-US/docs', b);
存储在变量d
上的URL是https://snyk.io/en-US/docs
。
URL模块的另一个功能是,它实现了WHATWG URL API,它遵守WHATWG的URL标准,供浏览器使用:
let adr = new URL("<https://snyk.io/en-US/docs>");
let host = adr.host;
let path = adr.pathname;
在上面的例子中,我们创建了一个名为adr
的URL对象。接着,代码获取URL的主机和路径名,分别是snyk.io
和/en-US/docs
。最后,我们可以将URL和允许列表或者黑名单进行对比,确保只有特定URL是被允许的。
如何使用正则验证
另一种验证URL的方法是使用正则表达式(regex)。我们可以使用Regex来检查URL是否有效。
使用regex进行URL验证的JavaScript语法是:
function isValidURL(string)
{
var res =
string.match(/(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-
]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]
\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|w
ww\.[a-zA-Z0-9]+\.[^\s]{2,})/gi);
return (res !== null);
};
来测试一些URL:
var tc1 = "<http://helloworld.com>"
console.log(isValidURL(tc1));
regex定义的URL语法检查URL是否以http://
或https://
或子域开始,以及是否包含域名。控制台上的语句结果是true
,因为它遵循了由regex定义的URL语法。相反,下面的语句将返回一个false
,因为它没有以任何允许的方案或子域开始,也不包含域名:
var tc4 = "helloWorld";
console.log (isValidURL(tc4));
上面的正则表达式相对简单,但仍然难以驾驭。这也是一个容易出错的方法,因为一个正则表达式不能充分处理验证URL的规则。它最多只能做到匹配有效的URL。此外,当一个正则表达式要么包含复杂的验证逻辑,要么收到冗长的输入字符串时,执行验证检查就变得很耗时。
为了满足定义的正则表达式验证检查,浏览器必须在输入字符串中进行数以百万计的回溯。如此多的回溯检查可能会导致"灾难性的回溯",这种现象是复杂的正则表达式会冻结浏览器或使CPU核心进程爆满。
安全使用JavaScript
正如SSRF被添加到新的OWASP Top 10中所证明的那样,URL验证对于JavaScript应用程序的安全性已经变得越来越关键。幸运的是,我们可以通过在服务器端验证URL来帮助缓解此类攻击。此外,根据验证和处理URL的首选方式来使用new URL
函数会非常有益。
在看到new URL
函数的一些使用案例后,我们学习了如何用正则表达式验证一个URL--并看到了为什么这种方法很麻烦而且容易出错。
URL的安全风险与其说是关于其有效性,不如说是关于危险的URL方案。因此,我们需要确保让服务器端的应用程序进行验证。攻击者可以绕过客户端的验证机制,所以仅仅依靠它并不是解决办法。
以上就是本文的所有内容,如果对你有所帮助,欢迎点赞、收藏、转发~
- 本文译自:https://snyk.io/blog/secure-javascript-url-validation/
- 作者:Mannan Tirmizi
JavaScript 如何验证 URL的更多相关文章
- 使用Javascript快速获取URL参数
首先:原文在这 Quick Tip: Get URL Parameters with JavaScript function getAllUrlParams(url) { var queryStr ...
- Javascript 获取链接(url)参数的方法
有时我们需要在客户端获取链接参数,一个常见的方法是将链接当做字符串,按照链接的格式分解,然后获取对应的参数值.本文给出的就是这个流程的具体实现方法. 当然,我们也可以用正则直接匹配,文章中也给出了一个 ...
- 关于去除Eclipse对JavaScript的验证
关于去除Eclipse对JavaScript的验证 在我们使用大量JavaScript作为一些UI或其他组件来使用时,很多情况下,明明引用的这些JavaScript是可以正常使用的,但Eclipse却 ...
- JavaScript 数据验证类
JavaScript 数据验证类 /* JavaScript:验证类 author:杨波 date:20160323 1.用户名验证 2.密码验证 3.重复密码验证 4.邮箱验证 5.手机号验证 6. ...
- javascript数字验证输入
javascript数字验证功能: <html> <body> <p>请输入数字.如果输入值不是数字,浏览器会弹出提示框.</p> <input ...
- javascript实现验证身份证号的有效性并提示
javascript实现验证身份证号的有效性并提示 function nunber(allowancePersonValue){ if(allowancePersonValue=="身份证号 ...
- javascript:将URL的参数列表解析为一个对象
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- 验证url格式
//验证url var url=$("#address").val(); var regUrl = /^http[s]{0,1}:\/\/.+$/ ; if(url.match(r ...
- JavaScript&jQuery获取url参数方法
JavaScript&jQuery获取url参数方法 function getUrlParam(name){ var reg = new RegExp("(^|&)" ...
- JS中验证URL、图片
//验证URL function IsURL (str_url) { var strRegex = '^((https|http|ftp|rtsp|mms)?://)' + '?(([0-9a-z_! ...
随机推荐
- python调用c++生成的dll
前言 这个我查询了很多资料,所以到此为止,相当于做一个总结 c++代码如何生成dll #include<iostream> using namespace std; extern &quo ...
- 关于 risrqnis
这道题里最有用的( Range Insert Subset Range Query [n?] In Set 破案了 我那五个点是因为维护不知道有什么用的东西炸了 删了就过了 题面 [JRKSJ R4] ...
- 【Flume】概述及组成、入门案例、进阶(事务、拓扑结构)、不同拓扑案例、自定义、数据流监控Ganglia
一.概述 1.定义 日志采集.聚合.传输的系统,基于流式结构 即:读取本地磁盘数据,写入HDFS或kafka 2.架构 Agent:JVM进程,以事件形式将数据送到目的地. Agent由三部分组成:S ...
- 动手实验查看MySQL索引的B+树的高度
一:文中几个概念 h:统称索引的高度: h1:主键索引的高度: h2:辅助索引的高度: k:非叶子节点扇区个数. 二:索引结构 叶子节点其实是双向链表,而叶子节点内的行数据是单向链表,该图未体现. 磁 ...
- Rust学习之旅(读书笔记):枚举 (Enum)
Rust学习之旅(读书笔记):枚举 (Enum) C 语言的枚举类型很弱,不如后来的语言,也不如之前的语言.在 C 语言里面枚举量就是一个名字,更方便的定义常量.今天读了<The Rust Pr ...
- 视图 触发器 事务 MVCC 存储过程 MySQL函数 MySQL流程控制 索引的数据结构 索引失效 慢查询优化explain 数据库设计三范式
目录 视图 create view ... as 触发器 简介 创建触发器的语法 create trigger 触发器命名有一定的规律 临时修改SQL语句的结束符 delimiter 触发器的实际运用 ...
- Linux基础第一章 概述
第一章 概述 1.1 前言 本章讨论系统的概念,从硬件.操作系统角度更加深刻的理解计算机系统,并快速浏览Linux系统提供的服务. 1.2 系统组成 1.3 操作系统和应用程序 操作系统这个词 ...
- 物联网 IOT 设备如何脱离信息孤岛?
以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「englyf」https://mp.weixin.qq.com/s/tb5eOFNUZLtPPLipLAh3vA 本文大概 1435 个 ...
- WCH网络授时芯片CH9126操作指导
目前CH9126推荐在Win7操作系统的电脑上执行,暂不推荐在与Win10系统的电脑进行通讯. 一.重要引脚说明 设置及状态相关引脚: 引脚1:RSETE-一个控制CH9126工号的引脚,直接接18K ...
- 软件安装——tortoiseGit安装和配置
Tortoisegit安装指南 TortoiseGit是一个开放的Git版本控制系统的源客户端,它是Git和Windows资源管理器的整合,提供了Git的图形化操作界面 一.软件安装 1.进入tort ...