资源和URL

资源

HTTP 请求的内容通称为“资源”。”资源“这一概念非常宽泛,它可以是一份文档,一张图片,或所有其他你能够想到的格式。每个资源都由一个 URI 来进行标识,例如下面的url其实是一张图片

1
https://pic.imge.cc/2024/08/11/66b8b34a1deb8.jpg

URL与URN

URL

网址即URL(统一资源定位符),也就是web地址,例如下面就是一个URL

1
https://ourobros.top

URL 由多个必须或可选的组件构成。下面给出了一个复杂的 URL

1
https://ourobros.top/xss%E6%BC%8F%E6%B4%9E%E7%9B%B8%E5%85%B3%E5%AD%A6%E4%B9%A0/
1
2
3
4
URL标准语法:协议://主机:端口/路径?参数1=值1&参数2=值2#片段标识符

##例如:(来自developer.mozilla.org)
http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument

协议

于大部分 Web 资源,通常使用 HTTP 协议或其安全版本,HTTPS 协议。另外,浏览器也知道如何处理其他协议。例如, 协议指示浏览器打开邮件客户端;协议指示浏览器处理文件传输。常见的方案有:mailto:ftp:(更多协议见下图)

主机

www.example.com 既是一个域名,也代表管理该域名的机构。它指示了需要向网络上的哪一台主机发起请求。当然,也可以直接向主机的 IP address 地址发起请求。但直接使用 IP 地址的场景并不常见

端口

:80 是端口。它表示用于访问 Web 服务器上资源的技术“门”。如果访问的该 Web 服务器使用 HTTP 协议的标准端口(HTTP 为 80,HTTPS 为 443)授予对其资源的访问权限,则通常省略此部分。否则端口就是 URI 必须的部分。

路径

路径(/path/to/myfile.html)是 Web 服务器上资源的路径。在 Web 的早期,类似这样的路径表示 Web 服务器上的物理文件位置。现在,它主要是由没有任何物理实体的 Web 服务器抽象处理而成的。

参数

?参数1=值1&参数2=值2(?key1=value1&key2=value2)是提供给 Web 服务器的额外参数。这些参数是用 & 符号分隔的键/值对列表。Web 服务器可以在将资源返回给用户之前使用这些参数来执行额外的操作。每个 Web 服务器都有自己的参数规则,想知道特定 Web 服务器如何处理参数的唯一可靠方法是询问该 Web 服务器所有者。

片段

#片段标识符(#SomewhereInTheDocument)是资源本身的某一部分的一个锚点。锚点代表资源内的一种“书签”,它给予浏览器显示位于该“加书签”点的内容的指示。例如,在 HTML 文档上,浏览器将滚动到定义锚点的那个点上;在视频或音频文档上,浏览器将转到锚点代表的那个时间。值得注意的是 # 号后面的部分,也称为片段标识符,永远不会与请求一起发送到服务器。

1
2
3
4
5
6
##例如
https://developer.mozilla.org/zh-CN/docs/Learn
tel:+1-816-555-1212
[email protected]:mdn/browser-compat-data.git
ftp://example.org/resource.txt
urn:isbn:9780141036144

URNs

URN 是另一种形式的 URI,它通过特定命名空间中的唯一名称来标识资源。

1
2
3
4
5
6
urn:isbn:9780141036144        
urn:ietf:rfc:7230

##上面两个 URN 标识了下面的资源:
乔治·奥威尔所著的《1984》
IETF 规范 7230,超文本传输 协议 (HTTP/1.1):Message Syntax and Routing.

Data URL

Data URL,即前缀为 data: 协议的 URL,其允许内容创建者向文档中嵌入小文件。它们之前被称作“data URI”,直到这个名字被 WHATWG 弃用。

1
2
3
4
5
6
7
#语法
前缀(data:)、指示数据类型的 MIME 类型、如果非文本则为可选的 base64 标记、数据本身
data:[<mediatype>][;base64],<data>

#mediatype 是个 MIME 类型的字符串,例如 'image/jpeg' 表示 JPEG 图像文件。如果被省略,则默认值为 text/plain;charset=US-ASCII。
#如果数据包含RFC3986中定义为保留字符的字符或包含空格符、换行符或者其他非打印字符(:, /, ?, #, [, ], @, !, $, &, ', (, ), *, +, ,, ;, =),这些字符必须进行百分号编码(又名“URL 编码”)。
#如果数据是文本类型,你可以直接将文本嵌入(根据文档类型,使用合适的实体字符或转义字符)。否则,你可以指定 base64 来嵌入 base64 编码的二进制数据。
1
2
3
4
5
6
7
8
9
10
11
12
#示例

#简单的 text/plain 类型数据。注意逗号URL编码为%2C,空格字符URL编码%20
data:,Hello%2C%20World!
# base64 编码版本
data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D

#一个 HTML 文档源代码 <h1>Hello, World</h1>
data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E

#带有<script>alert('hi');</script> 的 HTML 文档,用于执行 JavaScript 警告。注意,需要闭合 script 标签。
data:text/html,%3Cscript%3Ealert%28%27hi%27%29%3B%3C%2Fscript%3E

base64编码

Window.btoa()(也在 worker 中可用:从二进制数据字符串创建一个 Base64 编码的 ASCII 字符串(“btoa”应看作“从二进制到 ASCII”)

Window.atob()(也在 worker 中可用):解码通过 Base64 编码的字符串数据(“atob”应看作“从 ASCII 到二进制”)

linux中base64编码命令

1
2
3
4
5
6
7
echo -n hello|base64
# outputs to console: aGVsbG8=
echo -n hello>a.txt
base64 a.txt
# outputs to console: aGVsbG8=
base64 a.txt>b.txt
# outputs to file b.txt: aGVsbG8=

Window中进行base64编码

在 Windows 中,PowerShell 的 Convert.ToBase64String可用于执行 Base64 编码:

1
2
[convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("hello"))
# outputs to console: aGVsbG8=

另一种方案是:使用 GNU/Linux shell (例如 WSL)提供的使用工具 base64:

1
2
bash$ echo -n hello | base64
# outputs to console: aGVsbG8=

ps:但是感觉window中base64位编码最好的方法是找一个base64编码网站或者随便找个工具

[!NOTE]

许多安全问题(例如,钓鱼网站)已与 data URL 相关联,并在浏览器的顶层导航到它们。为了缓和这样的问题,在所有现代浏览器中,在顶层导航到 data: URL 是被禁止的。

MIME类型

介绍

MIME 类型通常仅包含两个部分:类型(type)和子类型(subtype),中间由斜杠 / 分割,中间没有空白字符:

1
type/subtype

类型代表数据类型所属的大致分类,例如 video 或 text

子类型标识了 MIME 类型所代表的指定类型的确切数据类型。以 text 类型为例,它的子类型包括:plain(纯文本)、html、calender(iCalendar/.ics 文件)

每种类型都有自己的一组可能的子类型。一个 MIME 类型总是包含类型与子类型这两部分,且二者必需成对出现。

有一个可选的参数,能够提供额外的信息:

1
type/subtype;parameter=value

例如,对于主类型为text的任何MIME类型,可以添加可选的charset参数,以指定数据中的字符所使用的字符集。如果没有指定 charset,默认值为ASCII(US-ASCII),除非被用户代理(User agent)的设置覆盖。要指定UTF-8文本文件,则使用MIME类型text/plain;charset=UTF-8

MIME 类型对大小写不敏感,但是传统写法都是小写。参数值可以是大小写敏感的。

分类

类型可分为两类:独立的(discrete)和多部分的(multipart)。独立类型代表单一文件或媒介,比如一段文字、一个音乐文件、一个视频文件等。而多部份类型,可以代表由多个部件组合成的文档,其中每个部分都可能有各自的 MIME 类型;此外,也可以代表多个文件被封装在单次事务中一同发送。多部分 MIME 类型的一个例子是,在电子邮件中附加多个文件。

独立类型

application:

不明确属于其他类型之一的任何二进制数据;要么是将以某种方式执行或解释的数据,要么是需要借助某个或某类特定应用程序来使用的二进制数据。通用二进制数据(或真实类型未知的二进制数据)是 application/octet-stream。其他常用的示例包含 application/pdfapplication/pkcs8和application/zip

audio:

音频或音乐数据。常见的示例如 audio/mpeg、audio/vorbis

example:

在演示如何使用 MIME 类型的示例中用作占位符的保留类型。这一类型永远不应在示例代码或文档外使用。example也可以作为子类型。例如,在一个处理音频有关的示例中,MIME 类型 audio/example 表示该类型是一个占位符,且在实际使用这段代码时,此处应当被替换成适当的类型。

font:

字体/字型数据。常见的示例如 font/woff、font/ttf 和 font/otf

image:

图像或图形数据,包括位图和矢量静态图像,以及静态图像格式的动画版本,如 GIF 动画或 APNG。常见的例子有 image/jpeg、image/png 和 image/svg+xml

model:

三维物体或场景的模型数据。示例包含 model/3mf 和 model/vrml

text:

纯文本数据,包括任何人类可读内容、源代码或文本数据——如逗号分隔值(comma-separated value,即 CSV)格式的数据。示例包含:text/plain、text/csv 和 text/html

video:

视频数据或文件,例如 MP4 电影(video/mp4)

[!NOTE]

对于那些没有明确子类型的文本文档,应使用 text/plain。类似的,没有明确子类型或子类型未知的二进制文件,应使用 application/octet-stream。

多部份类型

多部分类型指的是一类可分成不同部分的文件,其各部分通常是不同的 MIME 类型;也可用于——尤其在电子邮件中——表示属于同一事务的多个独立文件。它们代表一个复合文档

message:

封装其他信息的信息。例如,这可以用来表示将转发信息作为其数据一部分的电子邮件,或将超大信息分块发送,就像发送多条信息一样。例如,message/rfc822(用于转发或回复信息的引用)和 message/partial(允许将大段信息自动拆分成小段,由收件人重新组装)是两个常见的例子。

multipart:

由多个组件组成的数据,这些组件可能各自具有不同的 MIME 类型。例如,multipart/form-data(用于使用 FormData API 生成的数据)和 multipart/byteranges

比较重要的MIME类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#这是二进制文件的默认值
application/octet-stream

#这是文本文件的默认值
text/plain

#在网页中要被解析为CSS的任何CSS文件必须指定MIME为text/css
text/css

#所有的HTML内容都应该使用这种类型
text/html

#JavaScript内容应始终使用MIME类型text/javascript提供,使用除text/javascript以外的任何MIME类型都可能导致脚本无法加载或运行。
text/javascript

#图片类型
image/apng:动画便携式网络图形(APNG)
image/avif:AV1 图像文件格式(AVIF)
image/gif:图形交换格式(GIF)
image/jpeg:联合图像专家小组图片(JPEG)
image/png:便携式网络图形(PNG)
image/svg+xml:可缩放矢量图形(SVG)
image/webp:Web 图像格式(WEBP)

音频与视频类型

可用于HTML表单从浏览器发送信息给服务器

multipart/form-data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#作为多部分文档格式,它由边界线(一个由双横滑线 -- 开始的字符串)划分出的不同部分组成。每一部分有自己的实体,以及自己的 HTTP 请求头,Content-Disposition 和 Content-Type 用于文件上传字段。
Content-Type: multipart/form-data; boundary=aBoundaryString
(other headers associated with the multipart document as a whole)

--aBoundaryString
Content-Disposition: form-data; name="myFile"; filename="img.jpg"
Content-Type: image/jpeg

(data)
--aBoundaryString
Content-Disposition: form-data; name="myField"

(data)
--aBoundaryString
(more subparts)
--aBoundaryString--

如下所示的

1
2
3
4
5
6
7
8
9
10
11
<form
action="http://localhost:8000/"
method="post"
enctype="multipart/form-data">
<label>名字:<input name="myTextField" value="Test" /></label>
<label><input type="checkbox" name="myCheckBox" /> 勾选</label>
<label>
上传文件:<input type="file" name="myFile" value="test.txt" />
</label>
<button>发送文件</button>
</form>

会发送这样的请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
POST / HTTP/1.1
Host: localhost:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=---------------------------8721656041911415653955004498
Content-Length: 465

-----------------------------8721656041911415653955004498
Content-Disposition: form-data; name="myTextField"

Test
-----------------------------8721656041911415653955004498
Content-Disposition: form-data; name="myCheckBox"

on
-----------------------------8721656041911415653955004498
Content-Disposition: form-data; name="myFile"; filename="test.txt"
Content-Type: text/plain

Simple file.
-----------------------------8721656041911415653955004498--

multipart/byteranges用于把部分的响应报文发送回浏览器。

multipart/byteranges

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Type: multipart/byteranges; boundary=3d6b6a416f9b5
Content-Length: 385

--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 100-200/1270

eta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content
--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 300-400/1270

-color: #f0f0f2;
margin: 0;
padding: 0;
font-family: "Open Sans", "Helvetica
--3d6b6a416f9b5--

MIME嗅探

因为浏览器使用MIME类型,而不是文件扩展名来决定如何处理一个URL,所以Web服务器在响应的Content-Type头中发送正确的MIME类型非常重要。如果没有正确配置,浏览器很可能会误解文件的内容,网站将无法正常运行,下载的文件也可能会被错误处理。

为了解决这个问题,或者说是更好的用户体验,很多浏览器会进行MIME内容嗅探,也就是通过解析文件的内容,来猜测MIME类型的格式。

不同的浏览器处理MIME嗅探的方式是不一样的。但是他们都可能会产生严重的安全漏洞,因为有些MIME类型是可执行类型的,恶意攻击者可以通过混淆MIME嗅探算法,从而使攻击者可以进行网站运营者或用户都没有预料到的操作,如跨站脚本攻击。

如果不想浏览器端进行嗅探,可以在服务端的响应中设置 X-Content-Type-Options 头,比如:

1
X-Content-Type-Options: nosniff

MIME类型总结

text/plain表示文本文件的默认值。一个文本文件应当是人类可读的,并且不包含二进制数据。

application/octet-stream表示所有其他情况的默认值。一种未知的文件类型应当使用此类型。浏览器在处理这些文件时会特别小心,试图防止、避免用户的危险行为。

IANA 是 MIME 媒体类型的官方注册机构,并维护了官方所有 MIME 类型的列表https://www.iana.org/assignments/media-types/media-types.xhtml

http

协议

1
2
3
4
5
6
7
HTTP,超文本传输协议)是访问万维网使用的核心通信协议,也是今天所有Web应用程序使用的通信协议。最初,HTTP只是一个为获取基于文本的静态资源而开发的简单协议,后来人们以各种形式扩展和利用它.使其能够支持如今常见的复杂分布式应用程序。

HTTP使用一种用于消息的模型:客户端送出一条请求消息,而后由服务器返回一条响应消息。该协议基本上不需要连接,虽然HTTP使用有状态的TCP协议作为它的传输机制,但每次请求与响应交换都会自动完成,并且可能使用不同的TCP连接。

TCP就是一种传输协议,就像HTTP协议一样,HTTP的目的是指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应,而TCP的目的是为了确保数据传输的可靠性,我给你一个数据包,你一定就要收到,收不到的话那么我就会给你重发,直到我超时放弃你了。

HTTP是建立在TCP之上的,当你建立起TCP连接之后,在上面传输的数据用的是HTTP协议

请求头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
GET后面的/代表路径,HTTP/1.1代表HTTP的版本。

HOST表示请求的服务器网址

Connection表示持久的客户端与服务连接

Cache-Control表示缓存开关

sec-ch-ua可以理解用来替代user-agent的,用sec-ch-ua可以防止泄露浏览器详细信息

sec-ch-ua-mobile表示浏览器名称和版本

sec-ch-ua-platform表示操作系统名称

Upgrade-Insecure-Requests 请求头向服务器发送一个客户端对HTTPS加密和认证响应良好,在https页面中,如果调用了http资源,那么浏览器就会抛出一些错误。为了改变成这一状况,chrome(谷歌浏览器)会在http请求中加入 'Upgrade-Insecure-Requests: 1' ,服务器收到请求后会返回 "Content-Security-Policy: upgrade-insecure-requests" 头,告诉浏览器,可以把所属本站的所有 http 连接升级为 https 连接。

User-Agent表示发出请求的用户信息

Accept表示指定客户端能够接收的内容类型

Sec-Fetch-Site表示一个请求发起者的来源与目标资源来源之间的关系

Sec-Fetch-Mode该请求头表明了一个请求的模式

Sec-Fetch-Dest表示请求的目的地,即如何使用获取的数据

Sec-Fetch-User取值是一个Boolean类型的值,true(?1)表示导航请求由用户激活触发(鼠标点击/键盘),false(?0)表示导航请求由用户激活以外的原因触发

Accept-Encoding指定浏览器可以支持的web服务器返回内容压缩编码类型。

Accept-Language浏览器可接受的语言

Cookie 就是一段字符串,是浏览器保存服务器返回数据的方法,通常保存用户身份信息

X-Requested-With用于判断客户端请求是那种请求

referrer是HTTP请求header的报文头,用于指明当前流量的来源参考页面。通过这个信息,我们可以知道访客是怎么来到当前页面的。

文章参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP

http://t.csdnimg.cn/kyAFX