JavaEE-- 网络编程 http请求报头

  • URL 本身(即协议部分 http:// 或 https://)不会被加密 无论是 HTTP 还是 HTTPS,浏览器发请求时,域名和路径(URL)始终是明文的 ,不会被 TLS 加密。 被加密的只有 Header 和 Body 的内容
  • HTTPS 加密的是什么?
    • 请求的 Header(包括 Cookie、Authorization、Host 等字段)→ 加密
    • 请求的 Body(POST 数据、上传文件等)→ 加密
    • 响应的 Header 和 Body → 加密 但 https://example.com/login 这个完整的 URL 字符串,在传输过程中是明文的(DNS 查询和 TLS 握手阶段都能看到域名)。
  • 服务器收到请求后可以做最终校验 即使中间人只能看到明文的 URL(比如 https://example.com/api/v1/user),也无法看到:
    • Header 里你传的 token、Cookie
    • Body 里你提交的密码、个人信息 服务器拿到请求后,会对比:
    • URL 中写的路径(明文可见)
    • Header 中的 Host 字段(加密传输,只有服务器能解密看到) 如果两者不一致(比如 URL 是 example.com,但 Host 头被篡改为 fake.com),服务器可以拒绝这个请求,从而防止某些中间人攻击。

header 的整体的格式也是"键值对"结构.

每个键值对占一行.键和值之间使用分号分割. 报头的种类有很多,此处仅介绍几个常见的.

Host:表示服务器主机的地址和端口.
Content-Length表示body中的数据长度.
Content-Type 表示请求的body中的数据格式.

常见选项:

• application/x-www-form-urlencoded: form 表单提交的数据格式.此时body的格式形如:

java 复制代码
 title=test&content=hello

• multipart/form-data: form 表单提交的数据格式(在form标签中加上 enctyped="multipart/form-data" .通常用于提交图片/文件.body格式形如:

java 复制代码
 Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3Trw------WebKitFormBoundaryrGKCBY7qhFd3TrwA 
Content-Disposition: form-data; name="text" 
title ------WebKitFormBoundaryrGKCBY7qhFd3TrwA 
Content-Disposition: form-data; name="file"; filename="chrome.png" 
Content-Type: image/png 
PNG ... content of chrome.png ... ------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

• application/json: 数据为json格式.body格式形如

java 复制代码
 {"username":"123456789","password":"xxxx","code":"jw7l","uuid":"d110a05ccde64b1

关于 Content-Type 的详细情况:https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types

User-Agent (简称UA):

其中 Windows NT 10.0;

Win64; x64 表示操作系统信息

AppleWebKit/537.36 (KHTML, like Gecko) 游览器内核

Chrome/91.0.4472.77 Safari/537.36 表⽰浏览器信息.

User-Agent 之所以是这个样⼦是因为历史遗留问题.可以参考 User-Agent 的故事:https://zhuanlan.zhihu.com/p/398807396

表示浏览器/操作系统的属性.形如

java 复制代码
 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko
  1. 通过 UA 中的浏览器版本/操作系统版本,区分出当前用户的设备,最多都支持哪些特性
  2. UA也可以区分用户的设备,移动端还是PC端

响应式编程:根据屏幕尺寸自动切换样式

Referer 表示这个页面是从哪个页面跳转过来的.形如

如果直接在浏览器中输⼊URL,或者直接通过收藏夹访问页面时是没有Referer的.

Cookie 中存储了⼀个字符串,这个数据可能是客户端(网页)自行通过JS写入的,也可能来自于服务器 (服务器在HTTP响应的header中通过Set-Cookie字段给浏览器返回数据). 往往可以通过这个字段实现"⾝份标识"的功能.

每个不同的域名下都可以有不同的Cookie,不同网站之间的Cookie并不冲突. 可以通过抓包观察页面登陆的过程(以码云为例):

  • 你在浏览器输入 https://example.com 回车 → 首先发 3 个 TCP 握手包(这时候根本没有 Cookie!) → 握手成功 + TLS 握手完成
  • 浏览器真正开始发第一个 HTTP 请求(GET /) → 这个请求的数据包里才第一次可能出现 Cookie Header → 如果你之前没来过这个网站,Cookie 头是空的 → 如果你来过,浏览器会自动把之前 Set-Cookie 存的 cookie 塞进去
  • 你点登录、加购物车、翻页...... → 每点一次,就发一个新的 HTTP 请求数据包 → 每个包里都带着同样的 Cookie Header(除非服务器改了它)

右键可以删除,清空

重启访问服务器就可以找回了

为什么请求没有 Cookie,但响应却有 Set-Cookie?

服务器根本不关心你这次请求有没有带 Cookie,只要你访问了它,它就会"趁机"给你种新的 Cookie(或者重新种一遍)。

1) 清除之前的cookie

为了方便观察,先清除掉之前登陆的cookie

在码云页⾯上,点击url左侧的图标,选择Cookie

然后移除已经存在的Cookie

  1. 登陆操作 登陆请求
java 复制代码
POST https://gitee.com/login HTTP/1.1
 Host: gitee.com
 Connection: keep-alive
 Content-Length: 394
Cache-Control: max-age=0
 sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
 sec-ch-ua-mobile: ?0
 Upgrade-Insecure-Requests: 1
 Origin: https://gitee.com
 Content-Type: application/x-www-form-urlencoded
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/w
 Sec-Fetch-Site: same-origin
 Sec-Fetch-Mode: navigate
 Sec-Fetch-User: ?1
 Sec-Fetch-Dest: document
 Referer: https://gitee.com/login
 Accept-Encoding: gzip, deflate, br
 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
 encrypt_key=password&utf8=%E2%9C%93&authenticity_token=36ZqO9tglSN6EB6pF6f2Gt%2B

登陆响应

java 复制代码
 HTTP/1.1 302 Found
 Date: Thu, 10 Jun 2021 04:15:58 GMT
 Content-Type: text/html; charset=utf-8
 Connection: keep-alive
 Keep-Alive: timeout=60
 Server: nginx
 X-XSS-Protection: 1; mode=block
 X-Content-Type-Options: nosniff
 X-UA-Compatible: chrome=1
 Expires: Sun, 1 Jan 2000 01:00:00 GMT
 Pragma: must-revalidate, no-cache, private
 Location: https://gitee.com/HGtz2222
 Cache-Control: no-cache
 Set-Cookie: oschina_new_user=false; path=/; expires=Mon, 10 Jun 2041 04:16:00 -0
 Set-Cookie: gitee_user=true; path=/
 Set-Cookie: gitee-session-n=M1Rhbk1QUUxQdWk1VEZVQ1BvZXYybG13ZUJFNGR1V0pSYTZyTllE
 X-Request-Id: 77f12d095edc98fab27d040a861f63b1
 X-Runtime: 0.166621
 Content-Length: 92
 <html><body>You are being <a href="https://gitee.com/HGtz2222">redirected</a>.</
  1. 访问其他⻚⾯ 登陆成功之后,此时可以看到后续访问码云的其他页面(比如个人主页),请求中就都会带着刚才获取到 的Cookie信息
java 复制代码
GET https://gitee.com/HGtz2222 HTTP/1.1
 Host: gitee.com
 Connection: keep-alive
 Cache-Control: max-age=0
 Upgrade-Insecure-Requests: 1
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/w
 Sec-Fetch-Site: same-origin
 Sec-Fetch-Mode: navigate
 Sec-Fetch-User: ?1
 Sec-Fetch-Dest: document
 sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
 sec-ch-ua-mobile: ?0
 Referer: https://gitee.com/login
 Accept-Encoding: gzip, deflate, br
 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
 Cookie: oschina_new_user=false; user_locale=zh-CN; yp_riddler_id=1ce4a551-a160-4

理解登陆过程

一次会话(Session)的准确定义

从客户端与服务器建立认证关系(通常是登录)开始,到以下任意一种情况结束的整个过程:

  1. 用户主动退出登录
  2. Session 超时(常见 30 分钟不操作自动过期)
  3. 用户关闭浏览器(部分实现会销毁)
  4. 服务器主动销毁(踢人、下线)

这段时间内,用户发出的 所有 HTTP 请求 都属于同一次会话。

响应报头(服务器 → 浏览器)了解

认识请求"正⽂"(body)

正文中的内容格式和header中的Content-Type密切相关.上面也罗列了三种常见的情况. 下⾯可以通过抓包来观察这几种情况:

1) application/x-www-form-urlencoded 抓取码云上传头像请求

java 复制代码
 POST https://gitee.com/profile/upload_portrait_with_base64 HTTP/1.1
 Host: gitee.com
 Connection: keep-alive
 Content-Length: 107389
 sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
 Accept: */*
 X-CSRF-Token: 6ROfZGr4Y7Qx8td1TuKCnrG8gbODLCSUqUBZSw2b+ac=
 X-Requested-With: XMLHttpRequest
 sec-ch-ua-mobile: ?0
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
 Content-Type: application/x-www-form-urlencoded; charset=UTF-8
 Origin: https://gitee.com
 Sec-Fetch-Site: same-origin
 Sec-Fetch-Mode: cors
 Sec-Fetch-Dest: empty
 Referer: https://gitee.com/HGtz2222
 Accept-Encoding: gzip, deflate, br
 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
 Cookie: oschina_new_user=false; user_locale=zh-CN; yp_riddler_id=1ce4a551-a160-4
 avatar=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAPgAAAD4CAYAAADB0Ss
实际的抓包结果⽐较⻓,此处没有全部贴出.
 
 
  1. multipart/form-data
java 复制代码
POST https://v.bitedu.vip/tms/oss/upload/file HTTP/1.1
 Host: v.bitedu.vip
 Connection: keep-alive
 Content-Length: 293252
 sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
 Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjFiYThjMDM5L
 sec-ch-ua-mobile: ?0
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary8d5Rp4eJgrUSS3
 Accept: */*
 Origin: https://v.bitedu.vip
 Sec-Fetch-Site: same-origin
 Sec-Fetch-Mode: cors
 Sec-Fetch-Dest: empty
 Referer: https://v.bitedu.vip/personInf/student?userId=665
 Accept-Encoding: gzip, deflate, br
 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
 Cookie: rememberMe=true; username=18691491410; Admin-Token=eyJhbGciOiJIUzUxMiJ
------WebKitFormBoundary8d5Rp4eJgrUSS3wT
 Content-Disposition: form-data; name="file"; filename="
李星亚
  Java
开发⼯程师
.pdf"
 Content-Type: application/pdf
 %PDF-1.7
 %³  
1 0 obj
 <</Names <</Dests 4 0 R>> /Outlines 5 0 R /Pages 2 0 R /Type /Catalog>>
 endobj
 3 0 obj
 <</Author (  N v~N) /Comments () /Company () /CreationDate (D:20201122145133+06'
 endobj
 13 0 obj
 <</AIS false /BM /Normal /CA 1 /Type /ExtGState /ca 1>>
 endobj
  1. application/json

HTTP响应详解

认识"状态码"(statuscode)

状态码表⽰访问⼀个⻚⾯的结果.(是访问成功,还是失败,还是其他的⼀些情况...).

以下为常见 的状态码.

200OK

这是⼀个最常⻅的状态码,表⽰访问成功. 抓包抓到的⼤部分结果都是200 例如访问搜狗主页

java 复制代码
 HTTP/1.1 200 OK
 Server: nginx
 Date: Thu, 10 Jun 2021 06:07:27 GMT
 Content-Type: text/html; charset=utf-8
 Connection: keep-alive
 Vary: Accept-Encoding
 Set-Cookie: black_passportid=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; do
 Pragma: No-cache
 Cache-Control: max-age=0
 Expires: Thu, 10 Jun 2021 06:07:27 GMT
 UUID: 80022370-065c-49b0-a970-31bc467ff244
 Content-Length: 14805
 <!DOCTYPE html><html lang="cn"><head><meta name="viewport" content="width=device
 ......

注意:等待的过程就用 -表示

注意:在抓包观察响应数据的时候,可能会看到压缩之后的数据,形如:

⽹络传输中"带宽"是⼀个稀缺资源,为了传输效率更⾼往往会对数据进⾏压缩.

点击Fiddler中的

即可进行解压缩,看到原始的内容.

404NotFound

没有找到资源. 浏览器输入⼀个URL,目的就是为了访问对方服务器上的⼀个资源.如果这个URL标识的资源不存在, 那么就会出现404 例如,在浏览器中输⼊ www.sogou.com/index.html ,此时就在尝试访问sogou上的 /index.html 这个资源. 如果输⼊正确,则可以正确访问到.但是如果输⼊错误,比如 会看到404这样的响应

403Forbidden

表⽰访问被拒绝.有的⻚⾯通常需要⽤⼾具有⼀定的权限才能访问(登陆后才能访问).如果⽤⼾没有登陆 直接访问,就容易见到403.

例如:查看码云的私有仓库,如果不登陆,就会出现403.参考链接: https://gitee.com/HGtz2222/blog_python

405MethodNotAllowed

前⾯我们已经学习了HTTP中所⽀持的方法,有GET,POST,PUT,DELETE等. 但是对⽅的服务器不⼀定都⽀持所有的方法(或者不允许用户使用⼀些其他的方法). 这种情况我们后⾯学习了Servlet再演⽰.

500Internal Server Error

服务器出现内部错误.⼀般是服务器的代码执行过程中遇到了⼀些特殊情况(服务器异常崩溃)会产⽣这 个状态码. 咱们平时常用的网站很少会出现500(但是偶尔也能看到). 这种情况我们后面学习了Servlet再演演示

504GatewayTimeout

当服务器负载比较⼤的时候,服务器处理单条请求的时候消耗的时间就会很⻓,就可能会导致出现超时 的情况. 这种情况在双⼗⼀等"秒杀"场景中容易出现,平时不太容易见到.

服务器资源紧张常见

302Movetemporarily

临时重定向.

理解"重定向" 就相当于⼿机号码中的"呼叫转移"功能.

比如我本来的⼿机号是186-1234-5678,后来换了个新号码135-1234-5678,那么不需要让我的朋友知 道新号码,

只要我去办理⼀个呼叫转移业务,其他⼈拨打186-1234-5678,就会⾃动转移到135-1234-5678上.

在登陆页面中经常会见到302.⽤于实现登陆成功后⾃动跳转到主⻚. 响应报⽂的header部分会包含⼀个Location字段,表⽰要跳转到哪个页⾯. 例如:码云的登陆⻚⾯https://gitee.com/login 抓包看到的响应结果

前端网络请求演进史

1. jQuery.ajax(2010 年,江湖地位无人能撼)

javascript 复制代码
$.ajax({
    method: 'get',
    url: 'xxx',
    success: function(body) {  // 回调地狱的始作俑者
        console.log(body);
    }
});
  • 优点:跨浏览器兼容极好,当时 IE6/7 横行,jQuery 自动处理所有兼容性坑
  • 缺点:回调地狱,success/error/complete 三件套,代码嵌套层出不穷
  • 地位:2010-2015 绝对统治者,所有网站都在用

2. Angular HttpClient(2018 年,类型安全的王者)

javascript 复制代码
this.http.get<User[]>('api/users')
    .pipe(map(users => users.filter(u => u.active)))
    .subscribe(users => this.users = users);
  • 核心:基于 RxJS Observable(可观察流),不是 Promise
  • 优势:类型推断完美(TypeScript 友好),链式操作丝滑
  • 缺点:学习成本高,RxJS 陡峭的学习曲线
  • 适用:企业级 Angular 项目标配

3. Axios(2015 年,Vue/React 生态霸主)

javascript 复制代码
axios.get('xxx').then(response => {
    console.log(response.data);  // 自动解析 JSON
});
  • 杀手锏
    • 拦截器:请求前/后统一处理(加 token、处理错误)
    • 自动转换:自动 JSON.stringify/parse
    • 取消请求:支持 AbortController
  • 生态:Vue 官方推荐,React 社区也爱用
  • 现状:2024 年依然是主流选择
4. Fetch API(2017 年,浏览器原生标准)
javascript 复制代码
fetch('xxx')
    .then(response => response.json())  // 手动解析 JSON
    .then(data => console.log(data));
  • 优点:原生,无需额外库,现代语法
  • 缺点
    • 不自动解析 JSON(要手动 .json())
    • 不自动处理错误(4xx/5xx 也算成功)
    • 取消请求需要 AbortController(有点麻烦)
  • 现状:适合简单场景,复杂项目还是用 Axios
5. XMLHttpRequest(始祖,永远不会完全淘汰)

JavaScript

javascript 复制代码
const xhr = new XMLHttpRequest();
xhr.open('GET', 'xxx');
xhr.onload = function() {
    console.log(xhr.responseText);
};
xhr.send();
  • 地位:所有现代库的底层实现,浏览器原生最底层 API
  • 特点:回调式,原始粗暴,但最稳定

通过ajax构造HTTP请求

前端⻆度,除了浏览器地址栏能构造GET请求,form表单能构造GET和POST之外,还可以通过 ajax 的⽅式来构造HTTP请求.并且功能更强大

ajax 全称AsynchronousJavascriptAndXML,是2005年提出的⼀种JavaScript给服务器发送 HTTP请求的方式.

特点是可以不需要刷新页面/页面跳转就能进行数据传输.

在JavaScript 中可以通过ajax的方式构造HTTP请求

发送GET请求

javascript 复制代码
 <!-- 
引⼊
 jquery --> 
<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
 <script>
 $.ajax({
 type: 'get',
 url: 'https://www.sogou.com?studentName=zhangsan',
 success: function(data) {
 }
 });
 // 此处success 就声明了⼀个回调函数, 就会在服务器响应返回到浏览器的时候触发该回调
// 正是此处的 回调体现 "异步" 
// data 则是响应的正⽂部分.  
console.log("当服务器返回的响应到达浏览器之后, 浏览器触发该回调,们
console.log("浏览器⽴即往下执⾏后续代码");
 </script>

注意:如果把send中的地址改成其他服务器的地址(⽐如http://www.sogou.com/index.html这种), 大概率是会出错的.

这个错误是因为ajax默认不能"跨域",也就是"百度下⾯的html中的ajax不能访问搜狗的内容".这 样的设定也是完全合理的. 如果想要强⾏进⾏跨域,则需要服务器进⾏配合,在服务器的响应中"允许跨域"才可以. 咱们的⽰例服务器 42.192.83.143:8080/AjaxMockServer/info 进行了允许跨域设置,因 此我们的⻚⾯才能访问到其中的数据.

关于跨域这个话题,此处不深⼊讨论. 浏览器和服务器交互过程(引⼊ajax后)

在我们当前的例⼦中,test.html是通过本地⽂件的⽅式打开的,这个环节不涉及HTTP交互. 后⾯我们把test.html放到Tomcat上,就会产⽣上⾯的效果了

发送POST请求

对于POST请求,需要设置body的内容 1. 先使⽤setRequestHeader设置Content-Type 2. 再通过send的参数设置body内容.

发送application/x-www-form-urlencoded数据(数据格式同form的post)

javascript 复制代码
 <!-- 
引⼊
 jquery --> 
<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
 <script>
 $.ajax({
 type: 'post',
 url: 'https://www.sogou.com',
 contentType: 'application/x-www-form-urlencoded
 }
 });
 ',
 data: 'studentName=zhangsan',
 success: function(data) {
 // data 则是响应的正⽂部分.  
console.log("当服务器返回的响应到达浏览器之后, 浏览器触发该回调, 通知到咱们
console.log("浏览器⽴即往下执⾏后续代码");
 </script>

发送application/json数据:

javascript 复制代码
 <!-- 引⼊ jquery --> 
<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
 <script>
 $.ajax({
 type: 'post', url: 'https://www.sogou.com', contentType: 'application/json ',} });
 data: '{ name: "zhangsan" }',
 success: function(data) {
 // data 则是响应的正⽂部分.  
console.log("当服务器返回的响应到达浏览器之后, 浏览器触发该回调, 通知到咱们
console.log("浏览器⽴即往下执⾏后续代码");
 </script>

通过Javasocket构造HTTP请求

所谓的"发送HTTP请求",本质上就是按照HTTP的格式往TCPSocket中写⼊⼀个字符串. 所谓的"接受HTTP响应",本质上就是从TCPSocket中读取⼀个字符串,再按照HTTP的格式来解析. 我们基于Socket的知识,完全可以构造出⼀个简单的HTTP客⼾端程序,⽤来发送各种类型的HTTP请求

使⽤Java构造的HTTP客⼾端不再有"跨域"限制了,此时也可以来获取其他服务器的数据了

引入https ,SSL 与TLS

运行商劫:持:

相关推荐
鹿鸣天涯1 小时前
使用VMware Workstation 17虚拟机安装红帽企业版系统RHEL10
linux·运维·服务器
SKYDROID云卓小助手2 小时前
三轴云台之控制协同技术
服务器·网络·图像处理·人工智能·算法
艾莉丝努力练剑2 小时前
【Git:企业级开发模型】Git企业级Git工作流实战:基于Git Flow的分支模型与开发流程
服务器·git·ubuntu·gitee·centos·powershell·企业级开发模型
云边有个稻草人2 小时前
不用公网 IP 也能远程管 MongoDB?本地部署 + cpolar实用方案
网络协议·mongodb·cpolar
虹科网络安全2 小时前
艾体宝洞察 | 图数据驱动:网络安全威胁管理从分散情报到攻击图谱
网络·安全·web安全
杰 .2 小时前
Linux yum_and_apt
linux·服务器
南棱笑笑生2 小时前
20251129给荣品RD-RK3588开发板跑Rockchip的原厂Buildroot【linux-6.1】系统时适配AP6275P的蓝牙BLE
linux·运维·服务器·rockchip
Brown.alexis3 小时前
docker安装redis7
运维·docker·容器