Linux 网络:HTTP请求方法、状态码与登录状态

能够读懂 HTTP 报文后,浏览器与服务器之间的交互就有了形状:客户端发送方法、资源路径和数据,服务器返回状态码、报头和正文。但实际写网站时,还需要解释这些字段表达的行为。

例如,打开登录页面和提交用户名密码,都与登录有关,却不是同一种请求;返回“登录成功”后,下一次访问为什么还能识别用户;页面跳转时,浏览器是否会把刚才的密码再提交一次?

下面沿着表单提交与登录过程,理解请求方法、处理结果、重定向和状态管理之间的关系。

一、请求方法表达操作语义
请求目标说明“访问哪个资源”,方法说明“希望怎样操作它”。两者共同决定请求的含义。

GET /articles/10 HTTP/1.1
Host: blog.example
AI代码解释
http
1
2
这里表示获取文章资源。把方法换成 DELETE,语义就变成删除;服务器是否实现该操作、当前用户是否有权限,还需要分别判断。

方法 主要含义 常见用途
GET 获取资源的表示 打开网页、查询文章
HEAD 获取类似 GET 的响应信息,不发送响应正文 检查资源元信息
POST 请求资源按自身语义处理提交的数据 提交表单、创建订单
PUT 创建或替换目标资源的状态 按指定地址更新资源
DELETE 删除目标资源与其当前功能的关联 删除文章
OPTIONS 查询目标资源的通信选项 了解支持的方法等能力
POST 的含义不限于“新增”,PUT 也不能简单理解成“修改某一个字段”。接口应按方法语义设计,而不是看请求有没有正文就随意选择。HTTP 方法参考介绍了这些基本约定。

路由最好结合方法和路径匹配。GET /login.html 可以返回表单,POST /Login 负责处理提交的数据。若 /Login 只允许 POST,却收到 GET,可以返回:

HTTP/1.1 405 Method Not Allowed
Allow: POST
Content-Length: 0
Connection: close

AI代码解释
http
1
2
3
4
5
405 表示该资源不允许这个方法,Allow 列出允许的方法。它与“路径不存在”的 404 ,以及服务器不支持该方法功能的 501,有不同的含义。

二、安全性与幂等性
HTTP 所说的“安全方法”,是指客户端请求的语义应当是只读的,例如 GET 和 HEAD。服务器仍然可以记录访问日志,这类附带行为不等于客户端要求修改资源。

因此,不应把删除用户设计为一个普通 GET 链接。浏览器预取、爬虫访问或用户重复打开链接,都可能触发获取请求;让读取操作承担删除语义,会造成意料之外的结果。

幂等性关注重复请求的预期效果:同一个请求执行一次或多次,对目标资源产生的预期效果相同。PUT 和 DELETE 按规范具有幂等语义,POST 则不保证。

例如,反复把文章替换成同一份内容,目标状态仍相同;删除文章后再删除,文章仍然不存在。第二次删除可能返回 404,而第一次返回 204,这不妨碍删除操作的幂等性,因为幂等不要求响应逐字相同。

创建订单的 POST 若重复执行,可能产生多个订单,所以不能仅因为“刚才没收到响应”就无条件重发。安全性与幂等性的定义见 RFC 9110。

三、GET、POST 与数据的位置
GET 常把查询条件放在请求目标中:

GET /Search?name=linux&page=1 HTTP/1.1
Host: blog.example
AI代码解释
http
1
2
POST 常把要提交的数据放在正文中,但它也可以携带查询字符串。参数的位置与方法语义需要分别理解,不能把“URL 中有参数”当成 GET 的唯一判断标准。

GET 请求内容没有通用定义的语义,不宜依赖 GET 正文传递常规业务参数。另一方面,也不能把 POST 理解为“数据量无限大”:浏览器、代理和服务器都可能设置地址或正文大小上限。

另一个误区是“POST 比 GET 安全,所以密码用 POST 就不怕泄露”。POST 只改变组织方式,不会自动加密。把密码放入 URL 还容易进入历史记录和访问日志;采用 POST 正文提交后,网络传输仍应通过 HTTPS 保护。

页面中的 type="password" 也只是遮住屏幕上的输入,不会把字段自动加密。这些边界在排查表单时尤其重要:看不到明文输入,与请求内容已经受到保护,是不同的事情。

四、HTML 表单怎样变成请求
一个最小登录表单可以这样写:

<form action="/Login" method="post">
<label>用户名:<input name="name" type="text"></label>
<label>密码:<input name="passwd" type="password"></label>
<button type="submit">登录</button>
</form>
AI代码解释
html
1
2
3
4
5
action 指定提交目标,method 指定方法。输入框的 name 决定提交字段的键;id 主要用于页面元素关联,不能代替提交字段名。

没有指定其他编码类型的普通 POST 表单,通常使用 application/x-www-form-urlencoded。假设输入 alice 和 demo123,请求的关键部分是:

POST /Login HTTP/1.1
Host: blog.example
Content-Type: application/x-www-form-urlencoded
Content-Length: 25

name=alice&passwd=demo123
AI代码解释
http
1
2
3
4
5
6
正文末尾不额外添加换行时,这段内容为 25 字节。字段之间使用 & 分隔,键和值之间用 = 分隔。空格通常编码为 +,保留字符则可能使用百分号编码,例如值中的加号要编码为 %2B。

因此,服务端不能只做字符串切割而忽略解码。应先识别字段边界,再分别解码键和值,避免编码后的 & 被误当成新的字段分隔符。表单数据传输说明给出了编码方式。

服务端还需要检查字段是否缺失、长度是否合理,再执行身份校验。界面上弹出“注册成功”,或者路由函数始终返回 Login success!,都不能说明用户数据已保存、密码已验证。

五、状态码与处理结果
状态码是服务端对这次请求结果的协议级表达,第一位数字表示大类:

类别 含义 示例
1xx 中间信息 100 Continue
2xx 成功处理 200 OK、201 Created、204 No Content
3xx 重定向或缓存相关处理 303 See Other、304 Not Modified
4xx 请求或访问条件存在问题 400、401、403、404、405
5xx 服务端处理失败 500、502、503
200 常用于返回成功结果;201 表示创建了资源;204 表示成功但没有响应正文,不能再附上一段 JSON。状态码不只是页面上的提示文字,还会影响客户端处理方式。状态码参考列出了各类定义。

401 表示缺少有效认证凭据,响应应按规范带上 WWW-Authenticate 认证挑战;403 表示服务器拒绝处理请求,不能简单归结为“网络不通”。404 则表示没有找到目标资源,或服务器不愿披露其存在。

HTTP 状态也不能替代所有业务字段。计算接口可能收到合法请求,却发现除数为零;应用需要约定如何表达这种错误。应让状态码与正文含义配合,避免无论什么结果都返回 200,再让客户端猜测。

如果返回错误页面,仍可以设置 Content-Type: text/html。错误状态与正文类型不冲突,404 响应完全可以包含帮助用户返回首页的 HTML。

六、重定向会产生新的请求
重定向通常通过 3xx 状态码和 Location 指明另一个位置。例如:

HTTP/1.1 303 See Other
Location: /dashboard
Content-Length: 0
Connection: close

AI代码解释
http
1
2
3
4
5
浏览器接收后,可以再请求 /dashboard。原响应没有把新页面直接传回来,而是告诉客户端去哪里获取;这是两次不同的请求。

常用重定向的区别如下:

状态码 地址含义 跟随后请求方法
301 永久迁移 对 POST,客户端可能改为 GET
302 临时迁移 对 POST,客户端可能改为 GET
303 到另一地址获取结果 表单 POST 后通常改用 GET
307 临时迁移 保留原方法和正文
308 永久迁移 保留原方法和正文
登录提交成功后,若希望浏览器重新获取个人页面,303 的语义更明确。若使用 307,跟随后仍会提交原来的 POST 正文,不能把它当成“随便跳一个页面”。相关行为见 303 说明与 307 说明。

这种“POST 提交,再重定向到 GET 页面”的方式,称为 POST/Redirect/GET。用户刷新结果页时,通常重复的是 GET,而不是再次提交表单。但它不能独自解决请求超时重试或用户连续点击导致的重复业务操作。

资源不存在时,也不必先 302 跳到 /404.html。可以直接用 404 状态返回错误页,既保留原请求的结果,也少一次往返。

304 是需要单独理解的情况:它通常回应条件请求,告诉客户端可以使用已缓存的表示,不携带新的响应正文。它不是让浏览器访问另一个地址的普通跳转。304 说明介绍了这一缓存验证过程。

七、Cookie 与后续请求
HTTP 不会因为刚处理过登录请求,就自动为下一次请求保存用户身份。登录状态需要应用另行设计。

Cookie 是浏览器保存、并在满足条件时随请求携带的数据。服务器可以通过 Set-Cookie 下发,浏览器之后通过 Cookie 回传:

Set-Cookie: sid=opaque_session_id; Path=/; HttpOnly; Secure; SameSite=Lax
AI代码解释
http
1
上面的 opaque_session_id 只是占位示例。这里按 HTTPS 部署讨论;真正的会话标识应由服务器生成,而不是直接把用户名当作登录凭据。

后续请求中的形式是:

GET /dashboard HTTP/1.1
Host: blog.example
Cookie: sid=opaque_session_id
AI代码解释
http
1
2
3
Path、HttpOnly 等属性不会原样出现在 Cookie 请求字段里。它们是浏览器决定怎样保存和发送数据的规则。Cookie 使用指南说明了这一往返过程。

Cookie 也不只用于登录,界面主题和语言偏好都可以使用它。反过来,收到 Cookie: username=alice 并不能证明请求者就是 alice:客户端提交的数据仍需要经过验证。

八、Session 保存服务器端状态
一种常见登录方案,是由 Cookie 携带会话标识,由服务器会话保存用户信息。Session 通常包含用户编号、有效期以及必要的会话状态;具体权限还需要按业务规则检查。

会话存储
HTTP服务器
浏览器
会话存储
HTTP服务器
浏览器
POST /Login,提交凭据
校验凭据
创建会话,保存用户信息
303、Location、Set-Cookie
GET /dashboard,携带 Cookie
根据 sid 查询有效会话
返回用户信息
返回该用户可访问的页面
Cookie 可以理解为携带标识的渠道,Session 是服务器组织状态的一种方案。二者经常配合,但不是同一个概念。连接关闭后,新的连接仍可携带相同 Cookie,所以“保持登录”不依赖同一条 TCP 连接始终存在。

登录后应使用不可预测的会话标识,并在身份验证或权限变化时按需更新。服务器要检查会话是否存在、是否过期,不能只检查请求里有没有 sid。OWASP 会话管理指南讨论了会话标识和生命周期要求。

多进程服务还要考虑存储位置:如果会话只放在某个子进程的私有内存,下一次请求由另一个进程处理,就可能查不到。共享会话存储与网络连接处理,需要分别设计。

九、Cookie 属性与退出登录
属性 主要作用
Path 限定自动携带 Cookie 的路径范围
Domain 指定域范围;不设置时通常仅作用于当前主机
Max-Age 指定 Cookie 可保存的秒数
Expires 指定到期时间
Secure 限制通过安全连接发送
HttpOnly 阻止页面脚本通过常规 Cookie 接口读取
SameSite 限制某些跨站请求携带 Cookie 的条件
HttpOnly 不会阻止浏览器在脚本发起的请求中携带 Cookie。SameSite 可以减少部分 CSRF(跨站请求伪造)风险,但不能替代完整的请求校验。属性的具体语义见 Set-Cookie 文档。

Cookie 的客户端有效期与服务器会话有效期也不是一回事。浏览器还带着 Cookie,不代表服务器会话仍有效;不设置持久化期限,也不能武断认为关闭浏览器后一定彻底消失,因为浏览器可能恢复会话。

退出登录时,应使服务器端会话失效,同时让浏览器删除对应 Cookie:

Set-Cookie: sid=; Max-Age=0; Path=/; HttpOnly; Secure; SameSite=Lax
AI代码解释
http
1
删除时要匹配原 Cookie 的名称及域、路径范围。只删客户端 Cookie 而保留服务器会话,已经泄露的标识仍可能被使用。

另一个实现细节是多条 Set-Cookie 应分别输出,不能简单用逗号拼接。如果响应报头只用 unordered_map<string, string> 保存,同名键可能覆盖,第三篇实现报头容器时需要考虑这一点。

十、用 curl 观察登录流程
假设已经实现了登录和个人页面接口,可把下面的 blog.example 替换为自己的 HTTPS 测试站点。先提交测试数据,并把返回的 Cookie 保存到文件:

curl --http1.1 -i -c cookies.txt \
--data-urlencode 'name=alice' \
--data-urlencode 'passwd=demo123' \
https://blog.example/Login
AI代码解释
bash
1
2
3
4
--data-urlencode 对字段进行编码并采用 POST 提交,-c 保存 Cookie,-i 显示响应报头。接着携带已保存的 Cookie:

curl --http1.1 -i -b cookies.txt https://blog.example/dashboard
AI代码解释
bash
1
-b 让 curl 读取 Cookie 文件。若要观察重定向后的页面,可以增加 -L;保留不跟随重定向的请求,则便于直接查看最初的 303 和 Location。curl 手册与 Cookie 文档介绍了这些选项。

排查时依次确认请求是否命中正确的方法与路径、表单是否正确解码、凭据是否实际验证、响应是否设置 Cookie,以及后续请求能否查到有效会话。收到 200 或看到“登录成功”几个字,还不足以证明整条流程已经完成。

结语
请求方法描述客户端的操作意图,状态码说明服务器的处理结果,重定向把客户端引向下一次请求,Cookie 与会话则把多次请求关联到应用状态。

理解这条链后,登录不再只是一个返回字符串的函数。第三篇将继续把协议规则落实到 Linux HTTP 服务器中,处理请求解析、路由、静态资源与响应发送。
————————————————
版权声明:本文为CSDN博主「AbandonForce」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/AbandonForce/article/details/168881741

上一篇 银河麒麟桌面操作系统 V101常见问题3
下一篇 vcenter7.0.3j升级到7.0.3o