0.18 URL 结构拆解:地址栏那一长串在说什么
第〇篇【零基础预科】免费。这一篇把 URL 逐段拆开,让你彻底看懂地址栏。
一、URL 是什么
URL(Uniform Resource Locator,统一资源定位符) 是互联网上某个资源的完整地址,告诉浏览器:用什么协议、连哪台机器、找哪个资源、附带什么参数。
你可能会问:URL 和平时说的"网址"是一回事吗?日常说的网址基本就是 URL。它其实就是把前面几篇讲过的东西——协议、域名、端口、路径——拼成的一整串,你敲下回车,浏览器照着这串挨个去执行。你不用现在就背全,先把它当成"一张写全了的送货单":从用什么运输方式,到送到哪栋楼哪个房间,再到要不要顺带捎点别的货,全写在这一行里。
为什么要把这一串拆得这么细?因为安全测试时,每一段都可能是攻击入口:协议决定走没走加密,主机决定打到哪台机器,参数决定往后端传了什么数据。看懂 URL,本质就是先看懂"这个请求到底要去哪儿、又带了什么过去"。
二、逐段拆解
以这个 URL 为例:
https://gysec.top:443/wiki/deser-lazymap?from=home&tab=paid#section-2
└─┬─┘ └───┬───┘ └┬┘ └────────┬─────────┘ └──────┬───────┘ └───┬───┘
协议 主机 端口 路径 查询串 片段| 部分 | 例子 | 含义 |
|---|---|---|
| 协议 scheme | https:// | 用什么协议(http/https) |
| 主机 host | gysec.top | 域名或 IP |
| 端口 port | :443 | 可省略(https 默认 443,http 默认 80) |
| 路径 path | /wiki/deser-lazymap | 服务器上的资源/路由 |
| 查询 query | ?from=home&tab=paid | 传给服务器的参数 |
| 片段 fragment | #section-2 | 页内定位,不发给服务器 |
你会发现地址栏里大多数时候看不到端口这一段——因为 http 默认就是 80、https 默认就是 443,浏览器和服务器双方都心照不宣,所以可以省略。一旦你换成了非默认端口(比如本地开发时常开 localhost:8080),这一段就必须写出来,否则浏览器还按默认的 80 去找,自然连不上。至于"主机"那一栏,它也不一定是域名,直接填一个 IP(如 http://211.159.169.173/)一样能访问,只是没人愿意记一串数字。
三、查询字符串详解
以 ?id=1&name=abc&debug=true 为例:
- 以
?开始; - 多个参数用
&连接; - 每个参数是
键=值; - 特殊字符会被百分号编码(如空格成
%20、中文成%E4...)。
你的网站链接里出现过
?utm_source=gysec&utm_medium=about...,那就是一组用来统计流量来源的查询参数;?preview=member则用来在本地模拟会员态。
百分号编码(也叫 URL 编码)值得多看一眼:URL 里有一些字符是保留的——& 本来就是参数之间的分隔符,空格在地址栏里也不安全。所以只要参数值里恰好带了一个 & 或空格,它就会被编码:空格变成 %20,中文"测试"变成一串 %E6%B5%8B...。下次你在地址栏看到一堆 % 开头的怪字符,别以为是乱码,那多半就是被编码过的中文或特殊符号。
你可能会问:参数都写在 URL 里,那岂不是谁都能看见?是的,这正是 GET 的特点——查询参数会完整留在浏览器历史、服务器日志,甚至你随手分享出去的链接里。所以密码、验证码这类敏感信息,从来不放在 URL 参数里传,而是用 POST 放在请求正文里。以后看到一个链接后面挂着
?password=xxx,第一反应就该是"这写法太不专业了"。
四、路径与片段
- 路径:决定服务器把请求交给哪个页面/接口,本系列用的是"slug"(如
/wiki/deser-lazymap),编号不进 URL,改编号不会断链; - 片段
#:只在浏览器内用于滚动到某个标题/锚点,不会随请求发给服务器; - 结尾的
/表示目录(如/wiki/),有时有无斜杠会被当作不同地址。
关于片段 # 有个反直觉的点:它写在 URL 里,但根本不会被发送到服务器。你在服务器访问日志里翻烂了也看不到 #section-2——因为浏览器拿到页面后,是自己在本地找到那个标题滚过去的,压根没再问服务器。这也意味着:你想用 # 后面的内容做服务端判断是做不到的,服务器根本收不到。反过来,很多前端"单页应用"就爱用 # 后面那截表示当前在哪个页面,切换它不会真的重新请求服务器,只是前端自己换显示,又快又不刷新整页。
再补一个常被忽略的点:同一个路径,配上不同的查询参数,服务器可能返回完全不同的东西——/article?id=1 和 /article?id=200 走的是同一个程序,只是查出来的数据不同。这也是为什么做安全测试时,光盯着路径看不够,必须把 URL 后面所有参数都翻出来逐个试,真正藏问题的地方,往往就是这些不起眼的 ?key=value。
五、安全视角
URL 是 Web 攻击输入的主要载体之一:
- 查询参数被拼进 SQL → SQL 注入;
- 参数被拼进系统命令 → 命令注入;
- 参数被拼进文件路径 → 路径穿越;
- 参数里塞 URL → SSRF;
- 所以测试时第一件事,往往就是找出所有参数、观察它们被怎么使用。
举个最常见的例子:你打开一篇文章,地址是 article.php?id=1。顺手把 id=1 改成 id=2、id=100,如果页面内容跟着变了,说明这个 id 被直接拿去查数据库了——这时候在这个数字后面再加一个英文单引号,一旦页面报错或行为异常,就很可能藏着 SQL 注入。再比如某个 ?url=xxx 参数,你把 xxx 换成一个内网地址,要是服务器真替你去访问了,那就是 SSRF。安全测试里"篡改参数看它怎么反应"这一步,就是从这里开始的。
六、本篇小结
- URL = 协议 + 主机 + 端口 + 路径 + 查询串 + 片段。
- 查询串
?k=v&k2=v2传参,片段#仅浏览器内、不发服务器。 - 路径决定路由,slug 与编号解耦;特殊字符需百分号编码。
- 各类注入/穿越/SSRF 的输入常就在 URL 参数里。
下一篇 0.19 把整个过程串起来:从按下回车到页面出现,中间发生了什么。