linux篇【14】:网络http协议

目录

一.HTTP协议

1.认识URL

(1)域名->必须被转化成为IP

(2)URL中可以省略的部分

        ①端口号可缺省

        ②登录信息可以省略

        ③当我们访问自己的服务器时,https可省略,端口号不可省

(3)特定的服务 与 特定端口 的关系

(4)http协议是做什么的?

(5)如果我们client没有获取的时候,资源在网络服务器上

(6)资源文件在Linux服务器上

(7)Linux要如何找到这个文件呢?——通过路径!

2.urlencode和urldecode

二.http协议的请求格式

1.http协议的请求 分为三部分(我们这里以四部分解析)

(1)请求行

(2)请求报头

(3)空行

(4)有效载荷

<5>.请求实例

2.http响应

(1)响应行

(2)响应报头

(3)空行

(4)有效载荷

3.send 写入函数

4.telnet 命令——远程以协议方式登录某服务

(1)telnet请求服务器

(2)百度上请求服务器

三.http协议的响应,初步使用html

1.html

2.响应内容,使用html

 (1)

(2)Content-Length 保证能读取到完整的正文

 (3)把html和服务器工作解耦——readFile 要请求的资源

        ①文件在哪里? ——在请求的请求行中,第二个字段就是你要访问的文件 。

        ②GET /a/b/c.html http/1.0 中的 / 是web目录,不是根目录

四.表单

1.我们的网络行为有两种

HTTP/1.1协议中可使用的方法

2.GET方法

表单:

3.POST方法

4.GET Vs POST

5.代码

handlerHttpRequest 函数流程:

server.hpp

index.html

五.HTTP的方法与状态码

1.HTTP的方法

2.HTTP的状态码

六.HTTP常见Header

1.Location 重定向

七.常见Header——Cookie

1.Cookie介绍

(1)cookie详细介绍:

(2)Cookie用途:

(3)Cookie失效时间:

(4)cookie缺陷:

(5)cookie的属性

(6) 提高cookie安全性的几种方法

2.1 cookie登录策略(不安全的简单策略)

2.2 cookie+session 登录策略(安全策略)

(1)session详细介绍:

(2)session失效时间:

(3)session缺陷:

(4)(Session可以存放各种类别的数据,cookie只能存储字符串)

(5)session并不一定完全依赖于cookie实现

(6)cookie+session 登录策略(安全策略)

3. Connection

(1)Connection: closed —— 短链接(http/1.0)

(2)Connection: keep-aliye —— 长链接(http/1.1)

http协议无链接解释:


一.HTTP协议

虽然我们说, 应用层协议是我们程序猿自己定的 . 但实际上, 已经有大佬们定义了一些现成的 , 又非常好用的应用层协议 , 供我们直接参考使用 . HTTP( 超文本传输协议 ) 就是其中之一。
HTTP定义:超文本传输协议,是一个 无链接,无状态的应用层协议。

1.认识URL

平时我们俗称的 "网址" 其实就是说的 URL。
URL:统一资源定位服务(unit resource locate),用于在互联网中定位某种资源

https://www.baidu.com/         https://www.qq.com/

(1)域名->必须被转化成为IP

因为网络通信的本质: socket, IP+ port,所以(服务器地址)域名->必须被转化成为IP;访问网络服务,服务端必须具有port

(2)URL中可以省略的部分

        ①端口号可缺省

使用确定协议的时候,一般显示的时候,会缺省端口号

浏览器访问指定的url的时候,浏览器或app必须给我们自动添加port
浏览器如何得知,url匹配的port是谁呢?——特定的众所周知服务,端口号必须是确定的! !
httpserver—> 80
httpsServer—>443 sshd—> 22
用户自己写的网络服务bind端口的范围:[1024,n];因为前1023个是给httpserver这些服务的

        ②登录信息可以省略

登录信息我们一般放在页面上登录,一般不放在URL中,所以可以省略。 

        ③当我们访问自己的服务器时,https可省略,端口号不可省

当我们访问自己的服务器时,只需要IP+port:120.78.126.148:8080

https可省略,因为默认会选择https协议;登录信息一般放在页面上登录也可以省略;端口号不可省因为服务是我们自己写的,并不是众所周知服务

(3)特定的服务 与 特定端口 的关系

——>警察 与 110;抢救服务 与 120;火警灭火服务 与 119

(4)http协议是做什么的?

答:用于查阅文档,看音视频,这些都是以网页的形式呈现的。网页实际就是一个 .htmI文件
 http用途获取网页资源的,视频,音频等也都是文件!
解释:http是向特定的服务器申请特定的”资源”的,把资源获取到本地(本地可以是浏览器/app/迅雷播放器)进行展示或者某种使用的!

(5)如果我们client没有获取的时候,资源在网络服务器上

就在你的网络服务器(软件)所在的服务器(硬件,计算机)上

(6)资源文件在Linux服务器上

服务器都是Linux系统的,这些资源都是文件,即资源文件在Linux服务器上。要打开资源文件,读取和发送会给客户端——前提:软件服务器,必须先找到这个文件! !

(7)Linux要如何找到这个文件呢?——通过路径!

/ 就是Linux下的路径分隔符!

https://new.qq.com/rain/a720230106A0fRHW00

2.urlencodeurldecode

/ ? : 等这样的字符 , 已经被 url 当做特殊意义理解了 . 因此这些字符不能随意出现 . 比如, 某个参数中需要带有这些特殊字符 , 就必须先对特殊字符进行转义 .
转义的规则如下 :
将需要转码的字符转为 16 进制,然后从右到左,取 4 ( 不足 4 位直接处理 ) ,每 2 位做一位,前面加上 % ,编码成 %XY
格式

二.http协议的请求格式

1.http协议的请求 分为三部分(我们这里以四部分解析)

每行以 \r\n 结尾

(1)请求行

第一部分只有一行叫 请求行:包含了①请求方法 method。②url 一般省略了域名和端口,只有路径。③版本 http/1.1

注意:http协议请求时大小写是忽略的,例如请求行的 GET / HTTP/1.1  和get / http/1.1 都一样  

(2)请求报头

第二部分包含多行内容叫 请求报头:每一行包含很多请求属性,都是KV形式的,例如 Key: value(注意:和value中间有空格

(3)空行

第三部分只有一行叫 空行:因为只包含了一个 \r\n ,用与做分隔符,把报头和有效载荷分离

(4)有效载荷

第四部分只有一行叫 有效载荷:包含了请求正文:①登陆账号和密码。②个人信息/音频/视频等等。
注意:前三部分(请求行,请求报头,空行)都为http协议的报头;有效载荷就是个人信息

<5>.请求实例

我们利用百度向我们的服务器发起一个请求:

然后我们的服务器仅仅把收到的请求打印出来如下:

因为我们这次请求没有请求正文,所以不显示正文。行下面是第二次请求,因为浏览器是多线程请求,会发送多次请求;或者请求失败会继续发送请求,所以我们会受到多次请求。

DEBUG| 16733361461 whb | accept: Invalid argument | 125. 76.203.191[5129],socket fd: 4
125.76.203.191: 5129
GET / HTTP/1.1           
        ——GET:请求方法;/:是请求的资源。HTTP/1.1:(浏览器)版本
Host: 120. 78.126.148: 8080   
        ——要请求哪个主机,这个主机的IP和port
Connection: keep-alive        
        ——链接方式, keep-alive长链接
Cache- Control: max-age=0        
        ——#cache缓存-暂时不管
Upgrade- Insecure- Requests: 1    
        ——#协议升级-暂时不管
User- Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.3
        ——User- Agent浏览器版本
Accept: text/html,application/xhtml+xml,application/ xml;q=0.9,image/avif,image/webp , image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
        ——上面这个是可接受的资源种类
Accept- Encoding: gzip, deflate
        ——可接受的编码方式
Accept-Language: zh-CN, zh;q=0.9
        ——可接受的语言类型

2.http响应

也是每行以 \r\n 结尾

(1)响应

第一部分只有一行叫 响应:包含了①版本 http/1.1。②状态码。(例如404报错,200代表OK)③状态码描述。(例如404对应的“Not Found”描述)

(2)响应报头

第二部分包含多行内容叫 响应报头:每一行包含很多响应属性,都是KV形式的,Key: value(注意:和value中间有空格)比如 Content-Type: text/html; charset=utf-8 用于表示正文是 text/html文档类型,字符集为utf-8

(3)空行

第三部分只有一行叫 空行:因为只包含了一个 \r\n ,用与做分隔符,把报头和有效载荷分离

(4)有效载荷

第四部分只有一行叫 有效载荷:包含了响应正文:①htm/css/js/图片视频音频,自定义信息等——资源

http协议构建一个请求,响应

3.send 写入函数

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

把缓冲区buf中的len个长度数据写入 sockfd这个文件中,flags设为0,send和write函数等价

返回值:返回实际写入的字节数,错误返回-1错误码被设置

4.telnet 命令——远程以协议方式登录某服务

我们的服务器的响应内容:

(1)telnet请求服务器

先把./serverTcp 8080把服务器起来,然后telnet 127.0.0.1 8080,再 ctrl+],输入请求 GET / http/1. 0  ,就可以得到服务器的响应信息

(2)百度上请求服务器

IP+端口,就能得到响应

三.http协议的响应,初步使用html

1.html

HTML 教程 | 菜鸟教程 (runoob.com)

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
    <h1>我的第一个标题</h1>
    <p>我的第一个段落。</p>
</body>
</html>
  • <!DOCTYPE html> 声明为 HTML5 文档
  • <html> 元素是 HTML 页面的根元素
  • <head> 元素包含了文档的元(meta)数据,如 <meta charset="utf-8"> 定义网页编码格式为 utf-8
  • <title> 元素描述了文档的标题
  • <body> 元素包含了可见的页面内容
  • <h1> 元素定义一个大标题
  • <p> 元素定义一个段落 

2.响应内容,使用html

示例:

        HTTP/1.0 200 OK\r\n

         Content-Type 标定正文的类型

 (1)

解释下面:

——"HTTP/1.0 200 OK\r\n";        HTTP/1.0 版本,200状态码表示通过,OK状态码描述
——"Content-Type: text/html\r\n" ;    Content-Type内容类型,正文的类型是html文本类型。(text-文本类型)
——"\r\n";                                                       这是空行
——"<html><h1>hello bite</h1></html>\r\n";    正文内容是hello bite,<html>……</html>是html网页的格式,<h1>……</h1>是使正文成为大标题。(可以搜索html教程学习)

 

(2)Content-Length 保证能读取到完整的正文

任何协议的request or response:
报头+有效载荷
 ①http如何保证自己的报头和有效载荷被全部读取呢?
——无论是请求还是响应,读取完整报头:按行读取,直到读取到空行上

 ②你又如何保证 你能读取到完整的正文呢? ?
——报头能读取完毕,请求或者响应属性中”一定”要包含正文的长度!

 response += ("Content-Length: " + std::to_string(html.size()) + "\r\n");

 (3)把html和服务器工作解耦——readFile 要请求的资源

我要把特定的资源放到特定的目录下的文件中

        ①文件在哪里? ——在请求的请求行中,第二个字段就是你要访问的文件 。

例如:请求行:GET /a/b/c.html http/1.0 ,/a/b/c.html就是要访问的文件

        ②GET /a/b/c.html http/1.0 中的 / 是web目录,不是根目录

a前面的 / 不是根目录, web根目录,但可以设置成为根目录

path = "/a/b/index.html";        ——请求的人请求的文件路径
resource = "./wwwroot"; // 我们的web根目录,我们服务器内部给请求的路径自动加上前缀
resource += path; // ——> ./wwwroot/a/b/index.html
 

四.表单

1.我们的网络行为有两种

(1)我想把远端的资源拿到你的本地: GET /index.html http/1.1
(2)我们想把我们的属性字段,提交到远端,
提交到远端的两种方法:GET or POST
在HTTP中GET会以明文方式将我们对应的参数信息,拼接到url中

HTTP/1.1协议中可使用的方法

   当浏览一个Web页面时,客户端要向服务器发送请求,而这个请求中要包含请求的方法。HTTP协议/1.1支持的方法有:GET、POST、PUT、DELETE、HEAD、OPTIONS、TRACE、CONNECT。

2.GET方法

在HTTP中GET会以明文方式将我们对应的参数信息,拼接到url中        

表单:

    <form action="/a/b/c.html" method="get">    
——action文件路径; method打开方法(忽略大小写)
        Username: <input type="text" name="user"><br>
——input:渲染成输入框。类型是"text"文本类型。字段名称是"user"
        Password: <input type="password" name="passwd"><br>
——类型是"password"密码类型。字段名称是"passwd"
        <input type="submit" value="Submit">
——按钮类型是"submit",按钮名称是"Submit"
    </form>

3.POST方法

POST方法提交参数,会将参数以明文的方式,拼接到http的正文中来进行提交!

只需把method="get"  改成method="post"

4.GET Vs POST

1. GET通过url传参
2. POST通过正文传参
3. GET方法传参不私密(因为GET会把用户输入的有效信息用户名,密码等回显到浏览器)
4. POST方法因为通过正文传参,所以,相对比较私密一些(因为一些小白一般不会抓包看正文,所以相对私密)
5.GET通过url传参,POST通过正文传参,所以一般一些比较大的内容都是通过post方式传参的

6.HTTP GET请求提交参数长度限制;HTTP POST请求提交参数没有长度限制。

        解释6:Http Get方法提交的数据大小长度并没有限制,HTTP协议规范没有对URL长度进行限制。但是特定的浏览器及服务器对URL有限制,所以还是有限制的; 因为POST方法通过正文传参,理论上讲,POST是没有大小限制的。HTTP协议规范也没有进行大小限制,起限制作用的是服务器的处理程序的处理能力,而并非限制。

5.代码

TCP服务器的工作:——————(回忆)

init():①创建套接字。②填充服务器信息struct sockaddr_in。③将套接字和sockaddr_in 绑定bind。④socket设置为监听状态。

loop():⑤accept获取链接并获取客户端IP和port。⑥提供服务,读取内容后完成转换写回。

TCP客户端的工作:①创建套接字。② connect 填充服务器信息后向服务器发起链接请求。③写入数据后读出服务器转化的数据

handlerHttpRequest 函数流程:

①read读取客户端发来的请求。②从客户端请求的请求行中拿出请求的文件路径。③文件路径加上web根目录。④读取路径对应文件中的内容。⑤保存后缀,为下面响应做准备。⑥开始响应:响应报头类型根据文本/图片添加。响应为:响应行+响应报头(包括正文类型,正文长度)+空行+响应正文

server.hpp

#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <signal.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>
#include <cerrno>
#include <cassert>

#define CRLF "\r\n"
#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define HOME_PAGE "index.html"
#define ROOT_PATH "wwwroot"

using namespace std;

std::string getPath(std::string http_request)
{
    std::size_t pos = http_request.find(CRLF);
    if(pos == std::string::npos) return "";
    std::string request_line = http_request.substr(0, pos);
    //GET /a/b/c http/1.1
    std::size_t first = request_line.find(SPACE);
    if(pos == std::string::npos) return "";
    std::size_t second = request_line.rfind(SPACE);
    if(pos == std::string::npos) return "";

    std::string path = request_line.substr(first+SPACE_LEN, second - (first+SPACE_LEN));
    if(path.size() == 1 && path[0] == '/') path += HOME_PAGE;   
若客户端请求的只有一个web根目录,web根目录下那么多资源,不可能全给客户。
所以我们需要加上 index.html,让他只能访问到首页。

    return path;
}

std::string readFile(const std::string &recource)
{
    std::ifstream in(recource, std::ifstream::binary);
    if(!in.is_open()) return "404";
    std::string content;
    std::string line;
    while(std::getline(in, line)) content += line;
    in.close();
    return content;
}
void handlerHttpRequest(int sock)
{
    char buffer[10240];
    ssize_t s = read(sock, buffer, sizeof buffer);
    if(s > 0) cout << buffer;
    std::string path = getPath(buffer);    从客户端请求的请求行中拿出请求的文件路径
    // path = "/a/b/index.html";
    // recource = "./wwwroot"; // 我们的web根目录
    // recource += path; // ./wwwroot/a/b/index.html
    // 1. 文件在哪里? 在请求的请求行中,第二个字段就是你要访问的文件
    // 2. 如何读取
    std::string recource = ROOT_PATH;    
    recource += path;                    给客户端请求的文件路径加上web根目录
    std::cout << recource << std::endl;

    std::string html = readFile(recource);  读取recource这个路径对应文件中的内容
    std::size_t pos = recource.rfind(".");
    std::string suffix = recource.substr(pos);
    cout << suffix << endl;

    //开始响应
    std::string response;
    response = "HTTP/1.0 200 OK\r\n";    下面的if:若是图片,添加图片对应的文件后缀
    if(suffix == ".jpg") response += "Content-Type: image/jpeg\r\n";
    else response += "Content-Type: text/html\r\n";
    response += ("Content-Length: " + std::to_string(html.size()) + "\r\n");
    response += "\r\n";
    response += html;

    send(sock, response.c_str(), response.size(), 0);
}

class ServerTcp
{
public:
    ServerTcp(uint16_t port, const std::string &ip = "")
        : port_(port),
          ip_(ip),
          listenSock_(-1)
    {
        quit_ = false;
    }
    ~ServerTcp()
    {
        if (listenSock_ >= 0)    爷爷进程用listenSock_接客,最后还要关掉监听套接字
            close(listenSock_);
    }

public:
    void init()
    {
        // 1. 创建socket
        listenSock_ = socket(PF_INET, SOCK_STREAM, 0);
        if (listenSock_ < 0)
        {
            exit(1);
        }
        // 2. bind绑定
        // 2.1 填充服务器信息
        struct sockaddr_in local; // 用户栈
        memset(&local, 0, sizeof local);
        local.sin_family = PF_INET;
        local.sin_port = htons(port_);
        ip_.empty() ? (local.sin_addr.s_addr = INADDR_ANY) : (inet_aton(ip_.c_str(), &local.sin_addr));
        // 2.2 本地socket信息,写入sock_对应的内核区域
        if (bind(listenSock_, (const struct sockaddr *)&local, sizeof local) < 0)
        {
            exit(2);
        }

        // 3. 监听socket,为何要监听呢?tcp是面向连接的!
        if (listen(listenSock_, 5 /*后面再说*/) < 0)
        {
            exit(3);
        }
        // 运行别人来连接你了
    }
    void loop()
    {
        signal(SIGCHLD, SIG_IGN); // only Linux
        while (!quit_)
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);

            int serviceSock = accept(listenSock_, (struct sockaddr *)&peer, &len);
            if (quit_)
                break;
            if (serviceSock < 0)
            {
                // 获取链接失败
                cerr << "accept error ...." << endl;
                continue;
            }
            // 5.1 v1 版本 -- 多进程版本 -- 父进程打开的文件会被子进程继承吗?会的
            pid_t id = fork();
            assert(id != -1);
            if(id == 0)
            {
                close(listenSock_); //建议
                if(fork() > 0) exit(0);
                //孙子进程
                handlerHttpRequest(serviceSock);
                exit(0); // 进入僵尸
            }
            close(serviceSock);
            wait(nullptr);
        }
    }

    bool quitServer()
    {
        quit_ = true;
        return true;
    }

private:
    // sock
    int listenSock_;
    // port
    uint16_t port_;
    // ip
    std::string ip_;
    // 安全退出
    bool quit_;
};

index.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>104 期测试</title>
</head>

<body>
    <h3>hello my server!</h3>
    <p>我终于测试完了我的代码</p>
    <form action="/a/b/c.html" method="post">
        Username: <input type="text" name="user"><br>
        Password: <input type="password" name="passwd"><br>
        <input type="submit" value="Submit">
    </form>
    <!-- <img border="0" src="https://img1.baidu.com/it/u=1691233364,820181697&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500" alt="Pulpit rock" width="304" height="228"> -->
</body>

</html>

五.HTTP的方法与状态码

1.HTTP的方法

http1.0,三种:post,get,head

http1.1,八种:post,get,head,options,put,delete,trace,connect

其中最常用的就是GET方法和POST方法

HEAD请求是没有响应体的,仅传输状态行和标题部分

DELETE方法用来删除指定的资源,它会删除URI给出的目标资源的所有当前内容

PUT方法用于将数据发送到服务器以创建或更新资源,它可以用上传的内容替换目标资源中的所有当前内容

2.HTTP的状态码

最常见的状态码, 比如 200(OK)成功,404(Not Found)客户端错误,403(Forbidden),302(Redirect, 重定向)重定向,504(Bad Gateway)

4XX:客户端错误——>客户请求了不存在的资源,即客户提出了无理的要求,是客户的错。

5XX:服务器错误——>服务器代码中的内容错误,例如fork错误,就会返回5XX

(这里我们主要关注3XX)

response 结构图

六.HTTP常见Header

Content-Type: 数据类型(text/html等,比如 Content-Type: text/html; charset=utf-8 用于表示正文是 text/html文档类型,字符集为utf-8,不区分大小写 charset=UTF-8 也可以)

Content-Language:用于表示用户希望采用的语言或语言组合,比如 Content-Language: de-DE 表示该文件为说德语的人提供,但是要注意者不代表文件内容就是德语的。这里理解 Content-Type 和 Content-Language 区别: Content-Language更多表示上层语言的表示, 而Content-Type用于底层数据编码的表示

Content-Length: Body的长度

Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;

User-Agent: 声明用户的操作系统和浏览器版本信息;

referer: 当前页面是从哪个页面跳转过来的;

Location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问;

Set-Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能;

1.Location 重定向

301 代表 永久重定向/永久性转移 (Permanently Moved) ​ ;302 代表 暂时重定向/暂时性转移(Temporarily Moved )

区别:一个网站1如果临时不想被访问就用 302 暂时重定向 重定向到网站2;一个网站1如果永久不想被访问就用 301 永久重定向 重定向到网站2;

下面我们服务器的响应报头中请求属性加上Location重定向,我们在百度上url:124.71.81.109:8080 请求服务器时,会跳转到qq这个网站。

 

七.常见Header——Cookie

1.Cookie介绍

http协议特点之一:无状态(用户的请求行为,http协议本身这个网络通信不做记录,但http协议会采取周边策略去保持会话)
用户需要一个功能:会话保持(登录后一段时间访问资源不需要再登录)
一旦登陆,会有各种会话保持的策略——cookie

cookie:浏览器维护的文件(保存着用户名&&密码)
两种状态:①真正的存在磁盘。②内存级

(1)cookie详细介绍:

cookie是一种保存在客户端的小型文本文件,用于保存服务器通过Set-Cookie字段返回的数据,在下次请求服务器时通过Cookie字段将内容发送给服务器。是HTTP进行客户端状态维护的一种方式。而Set-Cookie以及Cookie字段可以包含有多条信息,也可以由多个Cookie及-Set-Cookie字段进行传输多条信息,并且cookie有生命周期,在超过生命周期后cookie将失效,对应的cookie文件将被删除。

注:HTTP的cookie是明文传送的,HTTPS是HTTP的加密传输,因此HTTPS的cooike是才密文传送的

(2)Cookie用途:

cookie的可以记录用户的ID,记录用户的密码,记录用户浏览过的商品记录。但是无法记录用户的浏览器设置(浏览器设置属于浏览器,而并不属于某次请求的信息)

(3)Cookie失效时间:

Cookie的Expires属性指定了cookie的生存期,默认情况下coolie是暂时存在的,他们存储的值只在浏览器会话期间存在,当用户退出浏览器后这些值也会丢失,如果想让cookie存在一段时间,就要为expires属性设置为未来的一个过期日期。现在已经被max-age属性所取代,max-age用秒来设置cookie的生存期。当没有设定过期时间时,则退出当前会话时cookie失效

        如果没有为Cookie指定失效时间,则设置的Cookie将在何时失效?

  • 如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览会话期的cookie被称为会话cookie。会话cookie一般不保存在硬盘上而是保存在内存里。
  • 如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间

(4)cookie缺陷:

cookie存在一定的缺陷:比如有大小限制,以及cookie不断的传递客户端的隐私信息,存在一定的安全隐患(比如认为篡改),因此有了session管理。(Session可以存放各种类别的数据,cookie只能存储字符串)

(5)cookie的属性

Cookie一共十个属性:

—— Name: Cookie名

—— Value: Cookie值

—— Domain: Cookie的域。如果设成.test.com,那么子域名a.test.com和b.test.com,都可以使用.test.com的Cookie。

—— Path: Cookie的路径。如果设成/path/,则只有路径为/path/的页面可以访问该Cookie。如果设为/,则本域名下的所有页面都可以访问该Cookie。

—— Expires / Max-Age:
解释1:Cookie的超时时间。若设置其值为一个时间,那么当到达此时间后,此Cookie失效。不设置的话默认值是Session,意思是Cookie会和Session一起失效。当浏览器关闭(不是浏览器标签页,而是整个浏览器)后,此Cookie失效。

解释2:指定了cookie的生存期,默认情况下cookie是暂时存在的,他们存储的值只在浏览器会话期间存在,当用户退出浏览器后这些值也会丢失,如果想让cookie存在一段时间,就要为expires属性设置为未来的一个过期日期。现在已经被max-age属性所取代,max-age用秒来设置cookie的生存期

—— Size: Cookie大小。

—— HttpOnly: (1)若此属性为true,则只有在http请求头中会带有此Cookie的信息,而不能通过document.cookie来访问此Cookie。(2)如果cookie中设置了HttpOnly属性,那么通过js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击,窃取cookie内容,这样就增加了cookie的安全性,但不是绝对防止了攻击

—— Secure: 设置是否只能通过https来传递此条Cookie。即:该Cookie是否仅被使用安全协议传输。安全协议有HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false。

—— SameSite:
用来防止 CSRF 攻击和用户追踪。
可以设置三个值:Strict、Lax 和 None。
Strict: Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。
Lax: Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。
None: 关闭SameSite属性,提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。

—— Priority: 优先级。定义了三种优先级,Low/Medium/High,当Cookie数量超出时,低优先级的Cookie会被优先清除。

例:

  1. 对保存到cookie里面的敏感信息加密
  2. 设置指定的访问域名
  3. 设置HttpOnly为true
  4. 设置Secure为true
  5. 给Cookie设置有效期
  6. 给Cookies加个时间戳和IP戳,实际就是让Cookies在同个IP下多少时间内失效

(6) 提高cookie安全性的几种方法

1.对保存到cookie里面的敏感信息必须加密

2.设置HttpOnly为true

3.设置Secure为true

4.给Cookie设置有效期

5.给Cookies加个时间戳和IP戳,实际就是让Cookies在同个IP下多少时间内失效

6.指定cookie domain的子域名

2.1 cookie登录策略(不安全的简单策略)

①从客户端向服务器输入我们的用户名和密码——>②服务器把 cookie用户名&&密码返回给客户端(在HTTP请求中的Cookie是明文传递的)——>③客户端下次登录 自动携带浏览器访问该网站对应的cookie文件中的内容,这样就能保持登录。

这样有安全隐患:当你下载了木马病毒,你的cookie用户名密码会被盗取,黑客会拿着你的cookie去登录,更严重的是黑客会修改你的cookie密码对账号产生威胁。

2.2 cookie+session 登录策略(安全策略)

(1)session详细介绍:

session服务器为了保存用户状态而创建的临时会话,或者说一个特殊的对象,保存在服务器中,将会话ID通过cookie进行传输即可,就算会话ID被获取利用,但是session中的数据并不会被恶意程序获取,这一点相对cookie来说就安全了一些,但是session也存在一些缺陷,需要建立专门的session集群服务器,并且占据大量的存储空间(要保存每个客户端信息)

(2)session失效时间

一般session的有效期默认是30分钟

(3)session缺陷

session也存在一些缺陷,需要建立专门的session集群服务器,并且占据大量的存储空间(要保存每个客户端信息)

(4)(Session可以存放各种类别的数据,cookie只能存储字符串)

(5)session并不一定完全依赖于cookie实现

一般情况下Session是通过Cookie传递Session_ID实现的,禁用cookie则session就没法用了,但是劳动人民智慧是无穷的,可以将SESSION_ID附着在URL中来实现,也就是session并不一定完全依赖于cookie实现

(6)cookie+session 登录策略(安全策略)

服务器形成的session文件:用户的临时私密信息,保存在这个文件中。
自动形成session文件的文件名叫session_id(文件名具备唯一性),(session_id是session的代号或者说唯一标识,通常是不重复的整数,但是其实是否用整数倒是无所谓,主要是唯一且要方便使用)

从客户端向服务器输入我们的用户名和密码——>服务器认证并形成session文件,用户的私密信息放在服务端的session文件中——>给客户端返回session_id——>将session_ id写入到本地的cookie中——>客户端下次登录 携带session_id,服务端找到session_id对应文件即可登录。

安全隐患减少了:

 ①损失小:黑客可能会在客户端盗取session_id,拿着session_id去登录,但至少户名&&密码是安全的,不会被改密码

 ②服务端有防范措施:服务器受到攻击怎么办?——大公司的服务端有能力防范;也有反诈陷阱,设置陷阱反向搜集黑客的信息,钓鱼执法。

3. Connection

(1)Connection: closed —— 短链接(http/1.0)

短链接一次只能处理一条http请求

用户所看到的完整的网页内容——背后可能是无数次http请求,每个图片就是一个文件,就需要一次请求
http底层主流采用的就是tcp协议,每处理一次请求就会进行一次 三次握手与四次挥手链接;一个网页有上百次http请求,就要进行上百次的 三次握手与四次挥手。则短链接不再适用。

(2)Connection: keep-aliye —— 长链接(http/1.1)

双方都同意采用长链接方案时,请求和响应中都携带了 Connection: keep-aliye ,客户端建立一个tcp链接,这一个tcp链接发送多次http请求,服务器接收后通过这个链接返回给客户端多次响应,当所有响应全部返回,此链接才断开。不用再向短链接那样重复建立链接了,大大提高了效率。

http协议无链接解释:

HTTP定义:超文本传输协议,是一个 无链接,无状态的应用层协议。

http协议底层是tcp,tcp是面向链接的,http只是使用了tcp的链接能力,但是http本身是无链接的。
 

  • 12
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值