学做网站论坛教程,cdn wordpress ip统计,学生做微商怎么加入,沈阳单页网站制作目录 1. HTTP请求方式
1.1. HTML 表单
1.2. GET POST方法
1.2.1. 用 GET 方法提交表单数据
1.2.2. 用 POST 方法提交表单数据
1.2.3. 总结
1.3. 其他方法
2. HTTP的状态码
2.1. 重定向
2.1.1. 临时重定向 永久重定向
2.1.2. 302 …目录 1. HTTP请求方式
1.1. HTML 表单
1.2. GET POST方法
1.2.1. 用 GET 方法提交表单数据
1.2.2. 用 POST 方法提交表单数据
1.2.3. 总结
1.3. 其他方法
2. HTTP的状态码
2.1. 重定向
2.1.1. 临时重定向 永久重定向
2.1.2. 302 307 的差别
2.1.3. Location 属性
2.1.4. HttpServer.cc (实现一个 302 重定向)
2.1.5. HttpServer.cc (实现一个 302 重定向 重定向到自己服务器上的资源)
3. HTTP 常见报头
4. 会话管理
4.1. HTTP 的特征
4.2. Cookie Set-Cookie
4.3. 网站如何进行用户管理
4.3.1. 方案一
4.3.2. 方案二
4.4. HttpServer.cc (包含 Cookie Set-Cookie )
5. 总结 1. HTTP请求方式 首先 我们要知道 客户平时的上网行为其实就两种 从服务端获取资源客户端通过发送 HTTP 请求到服务端从服务端获取各种资源如网页、图片、视频、文档等。这些资源是用户可以感知并理解的数据通过客户端的浏览器或应用程序展示给用户使用。当用户在浏览器中输入 URL 或点击链接时就是在请求服务端获取相应资源进行展示。将资源上传到服务器客户端也可以将一些数据或文件通过 HTTP 请求上传到服务器例如上传图片、视频、文档等文件。客户端可以通过表单提交、文件上传接口等方式将用户生成的数据或文件发送到服务端服务端接收和处理这些数据并根据业务需求进行相应操作。 因此HTTP 协议中的客户端主要是通过请求获取服务端的资源或将数据上传至服务器这些资源是用户能够感知和理解的各种形式的数据包括图片、视频、文档等。客户端和服务端之间的数据交互和资源传输是 Web 应用程序正常运行的基础。 在 HTTP 通信过程中服务器和客户端本质上可以被视为是两个独立的进程。 客户端进程发送 HTTP 请求到服务器并接收和处理从服务器返回的 HTTP 响应。 服务器进程负责接收来自客户端的 HTTP 请求处理请求并生成对应的 HTTP 响应 因此HTTP 请求和响应的传输过程实质上就是服务器进程和客户端进程之间的数据交互和通信即进程间通信。通过进程间通信客户端能够请求所需的资源并接收服务端返回的数据从而实现 Web 应用程序的功能和交互。 在一般的 HTTP 应用场景中GET 和 POST 方法是最常用的两种 HTTP 请求方法。 对于从服务器获取数据一般都是GET方法 对于向服务器提交数据 GET POST方法都可以但更多的是POST方法。 在一般的 HTTP 应用场景中大部分情况下 HTTP 请求方法就是 GET 和 POST两种方法通常可以满足大多数 Web 应用程序的需求。 其他的方法要么服务器不支持要么被服务端禁用了。在安全考虑和最小接口原则下服务端会限制或禁用一些不常用或潜在安全风险较大的 HTTP 请求方法。通过仅开放必要的请求方法可以减少潜在安全漏洞的可能性提高系统的安全性和稳定性。总的来说确保 Web 服务器提供最基本功能并保持安全性是很重要的因此一些不常用或不必要的 HTTP 请求方法可能会被禁用或限制。 为了解释 GET 和 POST 方式的差别我们需要引入一个表单的概念。 1.1. HTML 表单 表单在 Web 应用中通常用于收集用户输入的数据并将这些数据按照特定方式传输到服务器 (表单中是有方法 (method) 的)。当用户填写完表单后表单数据会被添加到 HTTP 请求的一部分然后通过网络发送到服务器端。 既然表单会作为 HTTP 请求的一部分 是需要提交给服务端的 因此需要指明 HTTP 的提交方法 GET、 POST因此我们就要看一看当用 GET 和 POST方法提交表单数据会有怎样的差异呢 首先我们先见一见下面这个表单 index.html !DOCTYPE html
html
headmeta charsetUTF-8meta nameviewport contentwidthdevice-widthtitle 咸蛋超人的网站 /title
/head
bodyform nameinput actionhaha.html methodGETUsername: input typetext nameuser brPaseword: input typepassword name password brinput typesubmit value登录/form
/body
/html action 和 method 是 form 表单元素的两个属性分别用于指定表单提交的目标URL和提交数据的HTTP请求方法action 属性用于指定表单提交的目标URL即在用户提交表单数据后数据将发送到该URL对应的服务器端资源进行处理。在这个例子中actionhaha.html 表示表单数据将提交到 haha.html 这个页面或资源method 属性用于指定提交表单数据时所使用的 HTTP 请求方法可以是 GET 或 POST。在这个例子中methodGET 表示表单数据将使用 GET 方法提交给服务器因此这个 HTML 中的 form 元素表示一个简单的登录表单当用户填写用户名和密码后点击登录按钮提交表单数据时数据将被以 GET 方法提交到 haha.html 这个目标URL。 1.2. GET POST方法 上面我们已经见了见表单现在我们就要分别以GET和POST方式将表单数据提交到服务端看看它们的差别是什么。 首先我们的准备工作 index.html就是我们服务端的默认首页也即是接下来的表单 haha.html就是表单中的action 也就是表单提交的目标URL error.html如果资源不存在状态描述符是404 其次 我们用的HTTP demo就是HTTP --- 上的 demo 1.2.1. 用 GET 方法提交表单数据
!DOCTYPE html
html
headmeta charsetUTF-8meta nameviewport contentwidthdevice-widthtitle 咸蛋超人的网站 /title
/head
bodyform nameinput actionhaha.html methodGETUsername: input typetext nameuser brPaseword: input typepassword name password brinput typesubmit value登录/form
/body
/html上面这个表单使用的提交方式是GET即以GET方式将表单数据提交到haha.html 这个网页中。 服务端跑起来因为这个表单此时是服务端的默认首页 (index.html)因此在浏览器输入IP:Port就会跳转到该表单页面具体如下 然后我们输入 Username Password假设我们分别输入李四123456 点击登录 注意我们观察输入前后的URL现象如下 HTTP请求如下 可以清楚的看到 当我们使用GET方法将表单数据传入服务端时此时表单数据作为查询字符串的一部分添加到了 URL 中。即此时HTTP请求的 URL 是表单中的action?表单输入的数据 (多个输入数据用 连接)。 总而言之GET 方法是将表单数据附加到HTTP请求的URL中传递给服务端这使得参数在 HTTP 请求中是可见的易于查看和理解。 1.2.2. 用 POST 方法提交表单数据
!DOCTYPE html
html
headmeta charsetUTF-8meta nameviewport contentwidthdevice-widthtitle 咸蛋超人的网站 /title
/head
bodyform nameinput actionhaha.html methodPOSTUsername: input typetext nameuser brPaseword: input typepassword name password brinput typesubmit value登录/form
/body
/html 服务端跑起来因为这个表单此时是服务端的默认首页 (index.html)因此在浏览器输入IP:Port就会跳转到该表单页面具体如下 然后我们输入 Username Password假设我们分别输入李四123456 点击登录 注意我们观察输入前后的URL现象如下 HTTP 请求如下 可以清楚的看到当表单使用 POST 方法提交时POST 方法通过 HTTP 请求的请求正文提交参数至服务器而非像 GET 方法那样将参数直接附加在 URL 中。这使得 POST 方法更适合用于传输敏感信息。如用户的登录凭证 (私密性) 或表单中的大量输入数据 (因为它不会添加到URL中)。 1.2.3. 总结 上面的过程大致是相同的只不过提交表单的方式不同罢了 但为了更好地理解我们可以画一下图形象的描述下这个过程 因为在我们的测试中服务端的默认首页就是表单因此客户端通过IP:Port就能访问到服务端的默认首页也就是表单表单收集用户的数据并将数据以特定的方式 (GET、POST) 传递给服务端。 GET方式是将表单数据附加到HTTP请求的URL中传递给服务端。由于数据明文添加在 URL 中因此用户输入的信息会在 URL 中回显不够私密适合传输一些不敏感的数据。 POST方式是将表单数据添加到HTTP请求的请求正文中传递给服务器。因为数据不会被明文附加在 URL 中用户输入的信息不会在 URL 中回显具有一定的私密性适合传输一些敏感数据如用户密码或个人信息。 上面提了一个私密性请注意私密性不等同于安全性。 由于HTTP协议是明文传输数据因此是具有一定的安全隐患的而私密性只不过可以让一些小白看不到罢了它不等同于安全性如果网络数据是以明文传送那么安全性无法得到保证只有对数据进行加密和解密才具有安全保证也就是我们后面要说的HTTPS协议。 具体讲 私密性仅仅意味着数据不会被直接暴露给普通用户但并不提供足够的保障以防止数据在传输过程中被拦截和窥视。在HTTP协议下数据是以明文形式传输的这意味着网络中的任何人都可以轻松地截取和查看传输的数据包括敏感信息。 因此即使使用了 POST 方法将数据放在请求正文中传输也无法确保数据的安全性。为了保障数据在传输过程中的安全确实需要对数据进行加密和解密。HTTPS 协议正是为了解决这一问题而设计的它通过使用 SSL/TLS 加密数据传输提供了一种经过加密保护的安全通信机制确保数据在传输过程中的机密性、完整性和信任。 这就是我们对GET和POST方法的理解done 1.3. 其他方法 当谈到 HTTP 方法时除了常见的 GET 和 POST 方法外还有一些其它的方法它们可能并不常用但简单了解一下还是需要的 方法 方法描述 PUT用于将请求的数据存储到指定的 URL 中类似于 POST 方法但 PUT 要求请求修改或替换指定的资源。 HEAD与 GET 方法类似但服务器不返回实体主体部分。主要用于获取资源的元数据如响应头信息、响应状态等。 DELETE用于请求服务器删除指定的资源。很显然这个方法服务端一般都会禁用。 OPTIONS用于获取目标资源所支持的通信选项这个方法可使服务器描述其支持的方法。 TRACE回显服务器接收到的请求用于诊断、测试或调试。 CONNECT用于将连接改为管道方式的代理服务器。通常用于 SSL / TLS 连接的建立。 LINK用于建立与资源的连接关系。 UNLINK用于断开资源与连接关系。 最后 对于HTTP请求方式 最常用的就是GET和POST其他都简单了解即可。 2. HTTP的状态码 进程有自己的退出码用于表示进程的执行结果而对于一个HTTP请求而言它也有自己的状态码用以表示这次 HTTP 请求的结果并且这个状态码都有与之匹配的状态码描述用来描述这次 HTTP 请求的结果。 状态码和状态码描述提供了关于请求处理情况的信息让客户端能够更好地了解服务器对请求的响应。具体如下 类别 原因短语1xxInformation (信息状态码)接受的请求正在处理2xxSuccess (成功状态码)请求正常处理完毕3xxRedirection (重定向状态码)需要进行附加操作以完成请求4xxClient Error (客户端错误状态码)服务器无法处理请求5xxServer Error (服务端错误状态码)服务器处理请求出错 接下来列举一些常见的状态码和相应的状态码描述 1xx 信息性状态码 100 Continue服务器已收到请求的部分需要客户端继续发送剩余部分。101 Switching Protocols请求切换协议服务器已经理解客户端的请求并将通过升级首部通知客户端使用不同的协议。 2xx 成功状态码 200 OK请求成功。201 Created请求已经被实现新资源已经创建。204 No Content服务器成功处理请求但未返回内容。 3xx 重定向状态码 301 Moved Permanently请求的资源已被永久移动到新位置。302 Found请求资源临时被移动。307 Temporary Redirect临时重定向。服务器要求客户端进行临时重定向至另一个 URL并且客户端应该保持原始的请求方法不变去请求新的 URL。 4xx 客户端错误状态码 400 Bad Request请求无效。401 Unauthorized请求需要用户认证。403 Forbidden服务器理解请求但拒绝执行。404 Not Found请求的资源未找到客户端的非法请求。 5xx 服务器错误状态码 500 Internal Server Error 服务器遇到错误无法完成请求。503 Service Unavailable 服务器当前无法处理请求。504 Gateway Timeout 网关超时。服务器作为网关或代理在设定的时间内无法从上游服务器或辅助服务器获得响应导致超时。 最后强调一下 HTTP状态码和状态码描述是有自己的标准的因此在未来我们编写HTTP代码时我们最好保持状态码和状态码描述一致这有助于确保代码的可读性、可维护性和互操作性。 2.1. 重定向
2.1.1. 临时重定向 永久重定向 临时重定向302 307 临时重定向状态码表示请求的资源暂时被移动到另一个位置客户端需要继续使用原始的请求 URI资源统一资源标识符来访问资源。这种情况下对用户的后续请求策略通常不产生影响因为服务器告诉客户端这是一个临时重定向客户端会继续使用原来的 URI。临时重定向常用于需要临时切换位置的情况比如临时维护、临时性重定向等。 永久重定向301 永久重定向状态码表示请求的资源已经永久性地移到了一个新的位置客户端应该记住这个变更并且使用新的位置来访问资源。这种情况下影响用户后续请求策略因为客户端会记住资源的永久转移并且之后的请求都会直接访问新的位置。永久重定向常用于需要长期改变资源位置的案例比如网站域名变更、资源永久移动等。 2.1.2. 302 307 的差别 302 Found 和 307 Temporary Redirect 确实都是表示临时重定向的状态码它们之间的主要区别在于处理重定向时对于原始请求方法的处理 302 Found 302 Found 是最常见的临时重定向状态码之一。当服务器返回 302 状态码时表示请求的资源暂时被移动到一个新的位置。客户端应该使用 GET 方法来重发请求。在使用 302 Found 时客户端在重定向请求时可能会将原始请求方法更改为 GET 方法导致 POST 请求被转换为 GET 请求可能会对业务逻辑产生影响。 307 Temporary Redirect 307 Temporary Redirect 也表示请求的资源暂时被移动到新的位置。与 302 不同的是307 要求客户端继续使用相同的请求方法。如果原始请求是 POST 方法重定向后的请求也应该是 POST 方法。使用 307 Temporary Redirect 可以确保客户端在重定向时保持原始请求方法不变避免了在处理 POST 请求时出现的问题。 因此虽然 302 Found 和 307 Temporary Redirect 都表示临时重定向但在处理原始请求方法上存在差别。如果需要保持原始请求方法不变可以选择使用 307 Temporary Redirect以确保请求在重定向后能够正确执行。 2.1.3. Location 属性 上面我们都是站在理论的角度看待重定向问题可是这个重定向过程究竟是怎样的呢 客户端发起 HTTP 请求客户端向服务器发送 HTTP 请求请求的资源可能由于某种原因需要重定向到另一个位置。服务器解析请求服务器接收到客户端的 HTTP 请求后会解析请求并发现需要重定向。服务器发送重定向 HTTP 响应当服务器确定需要进行重定向时会向客户端发送包含适当重定向状态码如 301、302、307 等的响应同时在响应报头中包含新的目标位置。客户端处理重定向客户端接收到包含重定向状态码的响应后根据状态码以及响应报头中的新目标位置信息会自动发起新的 HTTP 请求请求重定向后的资源。新的服务端响应新的服务端接收到客户端的请求后会处理请求并返回相应的 HTTP 响应数据。 总体来说重定向是通过在服务器对客户端的请求中返回特定的状态码和新的目标位置来触发的。客户端在接收到重定向响应后会根据新的目标位置继续请求资源从而完成整个重定向过程。 可是上面存在一个问题服务端是如何告诉客户端新的服务端的地址呢 换言之 服务端发送给客户端的 HTTP 响应中的什么属性包含了服务端的地址呢 答案是在HTTP响应报头中有一种属性Location其对应的值就是新的服务端的地址。 因此我们可以演示一下这个场景我们引用 HTTP --- 上的 3.3.3. 的代码在此基础之上做出更改。 2.1.4. HttpServer.cc (实现一个 302 重定向) 思路 当客户端要访问的资源路径服务端不存在时服务端返回一个带有302重定向的响应其中包含了 Location 属性就是重定向后的服务端的地址我们在这里以 cpluscplus网站为例代码如下 void HttpServerHandle(int sock)
{// 上面的代码没有做出更改, 在这里省略// 如果该文件不存在, 那么HTTP响应中的状态码就是404if(!in.is_open()){ // 302 重定向// 状态行(服务器端HTTP版本 状态码 状态码描述符\r\n)HttpResponse HTTP/1.1 302 Found\r\n;// 添加响应报头// Location 代表的就是重定向后的新的服务端的地址HttpResponse Location: https://cplusplus.com/\r\n;// 空行HttpResponse \r\n;// done}else{// 省略}// 读取文件完毕后, 关闭文件in.close();// 打印一下HTTP 响应std::cout **************************** std::endl;std::cout HttpResponse ;std::cout **************************** std::endl;// 发送给客户端send(sock, HttpResponse.c_str(), HttpResponse.size(), 0);
}
int main(int arg, char** argv)
{// 省略
} 同时我们将我们的默认首页也就是我们的 HTML 表单中的 action填一个不存在的资源如下所示 !DOCTYPE html
html
headmeta charsetUTF-8meta nameviewport contentwidthdevice-widthtitle 咸蛋超人的网站 /title
/head
bodyform nameinput actionabcdhaha.html methodGETUsername: input typetext nameuser brPaseword: input typepassword name password brinput typesubmit value登录/form
/body
/html 因为此时的action abcdhaha.html这个资源在我的服务端是不存在的 因此客户端通过我的IP:Port进入我的默认首页填充表单在以GET的方式将表单数据发送给服务端 (也就是登录)。 如下图所示 由于这个资源服务端不存在因此服务端打开文件会失败故会进入重定向的逻辑 而此时的Location填充的就是 cplusplus 这个网站因此此时浏览器就会跳转到 cplusplus 网站。 2.1.5. HttpServer.cc (实现一个 302 重定向 重定向到自己服务器上的资源) 当然我们也可以重定向到我们自己的服务器上的资源本质上我们只需要更改Location即可如下所示 void HttpServerHandle(int sock)
{// 上面的代码没有做出更改, 在这里省略// 如果该文件不存在, 那么HTTP响应中的状态码就是404if(!in.is_open()){ // 302 重定向// 状态行(服务器端HTTP版本 状态码 状态码描述符\r\n)HttpResponse HTTP/1.1 302 Found\r\n;// 添加响应报头// Location 代表的就是重定向后的新的服务端的地址HttpResponse Location: HTTP://82.157.67.44:8080/error.html\r\n;// 空行HttpResponse \r\n;// done}else{// 省略}// 读取文件完毕后, 关闭文件in.close();// 打印一下HTTP 响应std::cout **************************** std::endl;std::cout HttpResponse ;std::cout **************************** std::endl;// 发送给客户端send(sock, HttpResponse.c_str(), HttpResponse.size(), 0);
}
int main(int arg, char** argv)
{// 省略
} 现象如下 填充HTML表单并提交表单数据也就是登录。 我们的预期当登录后浏览器就会自动跳转到 error.html 这个网页。 如下图所示 这就是重定向的整个过程 done 3. HTTP 常见报头 当客户端发送 HTTP 请求或服务器返回 HTTP 响应时会使用各种不同类型的报头Header来携带和传递信息。下面是一些常见的 HTTP 报头 通用报头General Header Cache-Control控制缓存的行为例如缓存有效时间Connection指定与连接相关的选项close (短链接)keep-alive (长连接)Date提供消息创建的日期和时间Via指定代理服务器信息 请求报头Request Header Host指定被请求资源的主机名和端口号User-Agent包含发起请求的用户代理信息通常是浏览器或应用程序的标识Accept指定客户端接受哪些类型的响应内容Cookie包含客户端的 Cookie 信息Referer用于指示客户端发起当前请求的来源页面的地址。通俗讲当前页面是从哪个页面跳转过来的 响应报头Response Header Server提供关于服务器软件的信息Content-Type指定响应内容的类型 (例如 text/html(网页)、text/plain(纯文本) 等等)Set-Cookie服务器通过该报头将 Cookie 信息发送给客户端Location搭配3xx的状态码使用用于指定重定向的目标位置 实体报头Entity Header Content-Length指定响应正文的长度Content-Encoding指定响应正文的编码方式Content-Disposition指定如何显示响应正文通常用于下载文件 4. 会话管理
4.1. HTTP 的特征 简单快速HTTP是设计成简单且快速的协议它的简单性使得它容易实现同时也有利于减少通信的开销。无连接HTTP是无连接的也就是每次请求都需要创建新的连接而在请求结束后这个连接就会关闭。但是由于这种方式会带来一定的开销因此在实际应用中引入了持久连接HTTP keep-alive允许在单个连接上发送和接收多个请求与响应以减少建立和关闭连接的开销。无状态HTTP是无状态的这意味着服务器不会在多个请求之间保持任何状态信息。每个请求都是独立的服务器不会记住之前的请求状态。这就需要应用程序自己去维护客户端的状态例如通过Cookie等方式。 在这里解释一下无连接和无状态。 无连接我们之前说过 HTTP是一个应用层的协议底层采用的是传输层的TCP协议而TCP协议是面向连接的那为什么说HTTP是无连接的呢 很简单 在HTTP协议看来它只负责HTTP请求或响应数据的传输HTTP作为一个应用层协议并不直接处理连接的建立和维护而是依赖于底层的传输层协议TCP来处理连接相关的操作。即连接不是HTTP该考虑的事情这应该是TCP需要维护的因此 HTTP 是无连接的。 无状态什么叫做无状态呢 无状态Stateless是指HTTP协议本身不会在服务器端保留客户端请求的状态信息每个请求都是独立的服务器不会记住之前请求的信息。换句话说服务器不会对客户端的状态进行记录也不会保留关于客户端的会话信息。 可是不对啊我们在实际中使用的时候一般的网站是会记录下用户状态的啊。 例如一些网站登陆后如果关闭重新进入该网站此时依旧处于登陆状态啊这该如何解释呢 注意 虽然HTTP是无状态的 但并不代表这些网络服务不会记录用户的状态事实上 记录用户状态这件事情本来就不应该是HTTP该考虑的 而应该是由上层业务逻辑去考虑并实现的 HTTP 只要负责好网络功能就可以了。 因此虽然HTTP是无状态的 但是为了支持网站对用户状态进行管理在HTTP报头属性中有两个字段 Cookie (请求报头中涵盖的) Set-Cookie (响应报头中涵盖的)。 4.2. Cookie Set-Cookie 当客户端通常是浏览器首次访问一个使用了 Cookie 的网站时服务器会在响应报头中包含 Set-Cookie 字段用来在客户端存储一个名为 Cookie 的会话标识符。在随后的每次请求中客户端会将这个会话标识符通过 Cookie 字段发送回服务器。 Set-Cookie服务器在响应报头中设置的字段用来向客户端发送一个新的 Cookie。它包含了要在客户端存储的 Cookie 的名称、值以及其他属性如过期时间、域名、路径等。服务器可以通过 Set-Cookie 字段来指示客户端存储特定的会话标识符或其他信息。Cookie客户端在每次请求中发送的字段用来携带先前存储的 Cookie 信息。在客户端接收到服务器发送的 Set-Cookie 字段后将会在随后的每次请求中自动包含相应的Cookie字段以便服务器能够识别和关联每个请求属于哪个用户或会话。 这两个字段配合使用实现了在客户端和服务器之间传递和存储状态信息的功能用于实现用户状态的管理和保持。 4.3. 网站如何进行用户管理 为了更好地理解上面这两个属性我们来了解一般网站是如何进行用户管理的。 4.3.1. 方案一 客户端向服务端发起 HTTP 请求 在这里我们就具体一点输入用户的账号和密码服务端收到客户端的请求之后 服务端会对请求进行相关认证 (比如用户密码的验证)是否为合法用户如果是 服务端将该客户信息以及其它属性构成HTTP响应返回给客户端(上面就是一个登录的过程)此时客户端 (浏览器) 会维护一个 文件 or 内存文件该文件将浏览器曾经获得的私密信息 (用户名 密码) 保存起来 保存到浏览器本地。之后客户端的每一次 HTTP 请求会携带用户曾经输入的信息因此只要用户第一次成功登录后续再访问该网站就不需要再输入登录信息了即可以保证用户处于一种登陆状态我们一般将客户端 ( 浏览器 ) 中保存客户私密信息的文件称之为 Cookie 文件。 Cookie 有磁盘文件 也有内存级别的文件。浏览器通常会将 Cookie 存储在磁盘文件中以便将这些信息保存下来并在浏览器重新打开时仍然有效同时也会在内存中维护一份Cookie的副本用于实时的交互和状态共享。 那我们能不能看到这个 Cookie 呢 如下 上面的方案是存在严重问题的如下 有没有一种可能作为一个小白用户点了一个未知链接导致客户端 (浏览器) 被植入了木马程序此时这个木马程序就扫描用户的客户端 (浏览器)并查找和窃取保存在其中的 Cookie 文件并通过木马程序将 Cookie 文件(包含用户的私密信息) 推送给了其它人那么此时其它人就可以通过这个 Cookie 文件在自己的浏览器使用这些 Cookie 信息欺骗网站以用户的身份登录到相关网站甚至如果这个 Cookie 文件是明文保存用户的私密信息 那么就会导致用户信息严重泄漏甚至可能造成财产损失或其他安全问题。 可以看到这种方案实在是太不具备安全性了 因此在当今网络环境中 这种方案不会被采用因为它无法保证用户信息的安全性。 那该如何处理呢 这里的Cookie 文件不用了吗 答案是 还要用但方案需要做出调整如下 4.3.2. 方案二 客户端发起 HTTP 请求 输入相关信息 (用户名 密码)服务端收到HTTP请求后对用户信息进行相关认证验证成功后服务端会创建一个包含用户私密信息的文件并使用特定算法生成一个唯一的 session ID将该ID作为文件名服务端在 HTTP 响应中返回这个session ID 给客户端客户端本地维护 Cookie 文件并将服务端发送的 session ID 保存到 Cookie 文件中当然还有其他的信息 (诸如时间等等)当客户端再次访问该网站时会携带存储有 session ID 的 Cookie 文件服务端通过session ID进行识别和验证后续客户端再访问该网站就不需要再输入登录信息了即可以保证用户处于一种登陆状态 在方案一中这个 Cookie 文件保存的使用户的私密信息 又被泄露的风险而在方案二中Cookie 文件保存的是 session ID 不会泄露用户的私密信息。 可是这样就不会存在安全问题了吗如下 作为一个小白用户我又点了一个未知链接导致客户端 (浏览器) 被植入了木马程序此时这个木马程序就扫描用户的客户端 (浏览器)并查找和窃取保存在其中的 Cookie 文件并通过木马程序将 Cookie 文件( session ID) 推送给了其它人那么此时其它人就可以通过这个 Cookie 文件在自己的浏览器使用 session ID以同样的方式访问网站上的服务。 基于 session ID 的认证和状态管理方式 直接在Cookie存储用户私密信息 相比 虽然此时仍然存在被恶意程序窃取 Cookie 的风险但至少用户的私密信息不会明文暴露在 Cookie 里其它人通过这个被窃取的 session ID 虽然可以欺骗网站以用户的身份访问网站但他们无法获取用户的实际私密信息因为这些私密信息并没有存储在 Cookie 中而是由服务端在后台根据session ID和文件关联进行处理和验证。 session ID 这种策略本质上就是把用户信息的管理工作和会话保持工作全部交给服务端由服务端统一维护客户端只需要在初始登录时获取并保存session ID之后的会话管理和验证工作都由服务端负责。 那么有人说这种问题不能避免吗 答案是 不能避免。 在现实生活中无论多么强大的安全措施都无法完全避免账户被盗取或信息泄露等等问题的发生。我们能做的就是采取相关策略一定程度上降低发生这种事件的可能但无法完全避免这种事情。 针对账户安全和信息保护一些常见的策略包括 异地访问检测当用户的IP地址或其他访问特征发生异常变化时服务端可以将相关的session ID设置为失效状态要求用户重新进行身份验证。这可以帮助检测和防止恶意访问。超时策略通过设置 Cookie 文件中相关信息的超时时间可以控制用户会话的有效期一旦超过设定时间系统会要求用户重新登录从而降低长时间保持登录状态带来的风险。 这些策略可以在一定程度上增加账户和信息的安全性及时发现异常活动并减少恶意访问的可能性。同时用户也需要注意保护自己的账户信息如定期更改密码、不在不安全的网络环境下登录等。 尽管安全措施无法完全杜绝风险但我们可以通过综合利用不同的安全策略来降低被盗取或泄露的风险从而尽最大可能地保护用户的账户和信息安全。 4.4. HttpServer.cc (包含 Cookie Set-Cookie ) Set-Cookie 在 HTTP 响应中构造该报头向客户端写回 Cookie 信息 Cookie当客户端接收到包含 Set-Cookie 头部的 HTTP 响应时会自动将 Cookie 信息保存起来。在之后的每次HTTP请求中客户端会将之前保存的 Cookie 信息包含在 HTTP 请求报头的 Cookie 字段中发送给服务器。 在2.1.5. 基础之上做出更改 void HttpServerHandle(int sock)
{// 上面的代码没有做出更改, 在这里省略// 如果该文件不存在, 那么HTTP响应中的状态码就是404if(!in.is_open()){ // 302 重定向// 状态行(服务器端HTTP版本 状态码 状态码描述符\r\n)HttpResponse HTTP/1.1 302 Found\r\n;// 添加响应报头// Location 代表的就是重定向后的新的服务端的地址HttpResponse Location: HTTP://82.157.67.44:8080/error.html\r\n;// 空行HttpResponse \r\n;// done}else{// 状态行HttpResponse HTTP/1.1 200 OK\r\n;// Set-Cookie:HttpResponse Set-Cookie: 这是一个Cookie\r\n;// 空行HttpResponse \r\n;// 有效载荷std::string content;while(std::getline(in, content)){HttpResponse content;}// done}// 读取文件完毕后, 关闭文件in.close();// 打印一下HTTP 响应std::cout **************************** std::endl;std::cout HttpResponse ;std::cout **************************** std::endl;// 发送给客户端send(sock, HttpResponse.c_str(), HttpResponse.size(), 0);
}
int main(int arg, char** argv)
{// 省略
} 我们的预期现象 现象一当客户端用 IP:Port 进入我的服务端的默认首页也就是该表单此时浏览器就会有一个Cookie 文件 文件内容就是这是一个Cookie现象二当表单被提交也就是我们点击登录后 HTTP 会发起一个请求该请求内会有一个Cookie属性内容就是这是一个Cookie 现象一如下 符合预期 同时我们发现这个 Cookie 文件的到期浏览会话结束时它代表的是 如果此时浏览器退出了这个 Cookie 文件也就会消失这个 Cookie 文件属于会话级别的 Cookie 也称为会话 Cookie 或内存 Cookie会话 Cookie 是存储在内存中而不是硬盘上的文件中当用户关闭浏览器时会话Cookie会被删除因此在下次会话开始时不会保留任何信息这种Cookie对于临时保存用户数据并在会话结束时自动删除非常有用。 现象二如下 现象符合我们的预期。 5. 总结 至此我们的HTTP就结束了。我们学了什么呢 在 HTTP --- 上 我们对 URL 以及 Web 根目录有了一定的理解当然还有 HTTP 请求以及 HTTP 报头格式当然还有一些 HTTP demo在 HTTP --- 下 我们见了见 HTML 表单 借助表单理解了 GET 和 POST的差别以及了解了其他的请求方法在之后我们谈了 HTTP 状态码及其状态码描述 主要了解了重定向并通过相关 demo 加以验证其次 我们了解了常见的报头属性最后 我们谈了会话管理这个话题。 HTTP 的相关属性体现了协议的特点 (诸如特定的请求方式是什么意思特定的报头属性是什么含义如何区分报头和有效载荷等等) 同时 HTTP 协议通过行为单位将报头提取出来再通过报头的相关属性确定有效载荷体现了序列化和反序列化。 最后再介绍两个工具 Postman Fiddler Postman 功能可以通过 Postman 客户端向目标服务器构建HTTP请求特点提供了用户友好的界面支持创建和发送HTTP请求包括GET、POST、PUT、DELETE等并查看服务器响应。用户可以轻松设置请求参数、请求头、身份验证信息等也可以进行测试脚本编写、测试集合管理、环境变量管理等。用途开发人员可以使用Postman来快速测试API端点、验证功能、调试问题并共享和协作API测试集合。 Fiddler 功能Fiddler主要是用来进行抓包的。特点Fiddler可以截获计算机与网络之间的所有HTTP通信展示请求和响应的详细信息包括头部、正文、时间线等。同时还提供了各种调试功能如重放请求、修改请求/响应、自定义规则等。用途开发人员可以利用Fiddler来调试Web应用程序、排查网络问题、优化性能甚至模拟不同网络速度和条件下的交互情况。 HTTP是一种明文传送数据的协议。这意味着通过HTTP传输的数据在网络上是以明文形式传输的容易被攻击者窃听、篡改或偷取敏感信息。因此为了确保数据在传输过程中的安全性和保密性发展出了HTTPS协议。 HTTPSHyperText Transfer Protocol Secure是基于HTTP的加密通信协议通过在传输层上加入SSL/TLS协议来对HTTP数据进行加密和身份认证确保数据在传输过程中的安全。使用HTTPS协议可以保护用户数据的隐私和完整性有效抵御中间人攻击、窃取数据等安全威胁。 HTTP done HTTPS 见。