【4.0】基础串联之CookieSessionToken

发布时间 2023-07-26 10:45:27作者: Chimengmeng

【HTTP协议的缺陷】

无状态、无连接、基于请求响应、基于Tcp/Ip应用层协议

【1】无状态(Stateless):

  • HTTP协议是一种无状态协议,服务器不会保存请求和响应之间的状态信息。
  • 这意味着每次请求都是独立的,服务器无法直接识别来自同一个用户的多个请求。
  • 这样就需要使用各种机制(如Cookie、Session等)来维护用户的状态信息,以实现登录认证和保持会话等功能。

【2】无连接(Connectionless):

  • HTTP协议是一种无连接协议,即每次请求与响应之间都是相互独立的,服务器处理完一个请求后就会断开连接。
  • 这意味着对于每个请求都需要建立新的连接,可能会导致额外的延迟和资源消耗。
  • 为了解决这个问题,引入了持久连接和管线化技术,允许在一个连接上发送多个请求和响应,减少连接建立的开销。

【3】基于请求响应(Request-Response)模型:

  • HTTP协议采用请求与响应的方式进行通信。
  • 客户端发送请求到服务器,服务器处理请求并返回相应的响应。
  • 这种模型适用于大部分Web场景,但在一些特定情况下,如实时消息推送、服务器主动推送等,非常依赖于服务器主动发送消息给客户端,HTTP协议的请求响应模型有局限性。

【4】基于TCP/IP协议:

  • HTTP协议基于TCP/IP协议栈进行通信,借助传输层的可靠性和面向连接的特性。
  • 虽然TCP协议可靠,但对于某些资源密集型、高并发的场景,TCP协议的建立和连接维护会带来较大的开销。
  • 另外,使用TCP协议传输数据还可能面临拥塞控制和慢启动等问题。

【MySQL】

底层:C/S架构、底层基于Socket、自己封装的协议

客户端:Navicat(c++图形化界面,实现了请求和响应协议)、pymysql(用Python语言实现了请求和响应协议)

【1】底层架构:

  • C/S架构:
    • MySQL采用客户端/服务器(C/S)架构。
    • 这意味着在使用MySQL时,有一个MySQL服务器进程(通常称为mysqld),负责处理来自客户端的请求。
  • 基于Socket:
    • MySQL底层通过Socket进行网络通信。
    • 客户端与服务器之间建立Socket连接,通过发送请求和接收响应来实现数据交互。
  • 自己封装的协议:
    • MySQL使用自定义的协议进行请求和响应的交互。
    • 这个协议定义了数据包的格式、命令的编码和解析规则等。
    • 客户端和服务器需要遵守这个协议才能正常进行通信。

【2】客户端工具:

  • Navicat:
    • Navicat是一款流行的图形化界面的MySQL客户端工具,它使用C++语言实现了MySQL的请求和响应协议。
    • Navicat提供了直观的用户界面,方便用户进行数据库管理、查询、导入导出等操作。
    • 它可以帮助用户更轻松地与MySQL服务器进行交互。
  • pymysql:
    • pymysql是一个用Python语言开发的MySQL客户端库。
    • 它实现了MySQL的请求和响应协议,并提供了一组API供开发者使用。
    • 通过pymysql,开发者可以使用Python编程语言来连接MySQL服务器,执行SQL语句,获取查询结果等。
    • pymysql使得在Python程序中使用MySQL变得更加方便和灵活。

【3】总结起来

  • MySQL采用C/S架构,底层基于Socket通信,并使用自己封装的协议进行请求和响应的交互。
  • Navicat是一个图形化界面的MySQL客户端工具,通过实现请求和响应协议,提供了可视化的数据库管理功能。
  • 而pymysql则是一个用Python语言实现的MySQL客户端库,使得开发者能够用Python编写程序与MySQL服务器进行交互。

【Redis】

C/S架构、底层基于Socket、自己封装的协议

Redis(Remote Dictionary Server)是一种高性能的键值对存储系统

【1】C/S架构:

  • Redis采用客户端/服务器(C/S)架构。在该架构下,有一个Redis服务器进程(通常称为redis-server),负责处理客户端的请求。
  • 客户端可以通过与Redis服务器建立Socket连接来发送请求,并接收响应。这种架构允许多个客户端同时访问Redis服务器,实现了高并发的处理能力。

【2】底层基于Socket:

  • Redis底层通过Socket进行网络通信。客户端与服务器之间建立Socket连接,并使用TCP/IP协议进行数据传输。
  • 当客户端需要发送请求给Redis服务器时,它会将请求数据打包成数据包,并通过Socket发送给服务器。服务器接收到请求后进行处理,并将响应结果发送回客户端。这样就完成了客户端与服务器之间的通信和数据交互。

【3】自己封装的协议:

  • Redis使用自己封装的协议进行请求和响应的交互。该协议是基于TCP的流式协议,简洁且高效。
  • Redis协议使用文本格式,请求和响应都是以文本形式进行序列化,并通过特定的命令和参数传递。客户端发送请求时,需要按照协议规定的格式进行编码,而服务器则按照协议解析请求并返回响应。
  • Redis的协议支持多种类型的操作,如键值对存取、事务处理、发布订阅等。通过操作不同的命令和参数,客户端可以对Redis服务器进行灵活的控制和操作。

【4】综上所述

  • Redis采用C/S架构,底层基于Socket通信,并使用自己封装的协议进行请求和响应的交互。
  • 这种架构和协议设计使得Redis具有高性能、高并发和灵活的特点,适合用于缓存、会话管理、消息队列等各种场景。

【Docker】

C/S架构、底层基于Http协议、使用restful协议

【1】C/S架构:

  • Docker采用客户端/服务器(C/S)架构。在该架构下,有两个核心组件:Docker客户端和Docker引擎(也称为Docker守护进程)。
  • Docker客户端是用户与Docker交互的命令行工具或图形界面,负责发送指令给Docker引擎。而Docker引擎则是运行在主机上的后台进程,负责管理和执行容器化应用程序。
  • Docker客户端可以通过与Docker引擎建立Socket连接来发送命令,并接收来自引擎的响应。这种架构允许用户通过客户端与Docker引擎进行通信,控制容器的创建、启动、停止等操作。

【2】底层基于HTTP协议:

  • Docker引擎使用HTTP协议与Docker客户端进行通信。当Docker客户端发出命令时,它会将命令封装成HTTP请求,并通过特定的URL路径发送给Docker引擎。
  • Docker引擎接收到HTTP请求后进行解析,并执行相应的操作。执行结果会以HTTP响应的形式返回给Docker客户端。
  • 使用HTTP作为底层协议的好处是它简洁且易于使用,同时也方便与其他系统进行集成和通信。

【3】使用RESTful协议:

  • Docker采用RESTful协议设计其API接口。REST(Representational State Transfer)是一种基于HTTP的设计风格,通过统一的资源定位符(URL)和操作方法(GET、POST等)对资源进行访问和操作。
  • Docker的API将容器、镜像、网络等抽象为不同的资源,并使用HTTP的请求方式(GET、POST、PUT、DELETE等)对这些资源进行操作。
  • 例如,通过发送HTTP的POST请求给特定的URL路径可以创建一个新的容器,而发送DELETE请求则可以删除指定的容器。
  • RESTful风格的API设计使得Docker的接口简洁、易于理解和使用。

【4】综上所述

  • Docker采用C/S架构,底层基于HTTP协议进行通信,并使用RESTful协议设计API接口。
  • 这种架构和协议组合使得用户可以通过简单的命令或操作与Docker引擎进行交互,实现容器化应用程序的管理和控制。

【elasticsearch】

C/S架构、底层基于Http协议、使用restful协议

【1】C/S架构:

  • Elasticsearch采用客户端/服务器(C/S)架构。在该架构中,有两个核心组件:Elasticsearch客户端和Elasticsearch服务器。
  • Elasticsearch客户端是用户与Elasticsearch进行交互的接口,可以是命令行工具、编程语言的客户端库或可视化界面。它负责发送请求给Elasticsearch服务器,并解析服务器返回的响应。
  • Elasticsearch服务器是运行在集群中的一个或多个节点上的进程,负责存储和索引数据,执行搜索和分析等操作。服务器接收来自客户端的请求,执行相应的操作并返回结果。

【2】底层基于HTTP协议:

  • Elasticsearch的客户端和服务器之间使用HTTP协议进行通信。当客户端发送请求给服务器时,它会将请求封装成HTTP请求,并通过特定的URL路径发送给服务器。
  • 服务器接收到请求后进行解析,并执行相应的操作。执行结果以HTTP响应的形式返回给客户端,包含相关的数据或错误信息。
  • 基于HTTP协议的通信方式使得Elasticsearch非常容易与各种编程语言和工具进行集成。

【3】使用RESTful协议:

  • Elasticsearch的API设计遵循RESTful风格。RESTful是一种在设计网络应用程序时经常使用的架构风格,它使用统一的资源定位符(URL)和HTTP方法(GET、POST、PUT、DELETE等)对资源进行操作。
  • Elasticsearch将数据和功能封装为不同的资源,例如索引、文档、搜索等,每个资源都有一个唯一的URL路径来标识。
  • 使用HTTP的不同方法对这些资源进行操作,例如使用GET请求获取文档,使用POST请求创建索引,使用DELETE请求删除索引等。
  • 通过简洁的URL路径和HTTP方法,RESTful API使得Elasticsearch的接口易于理解和使用。

【4】总结:

  • Elasticsearch采用C/S架构,底层使用HTTP协议进行通信,并提供基于RESTful风格的API。
  • 这种架构和协议的组合使得用户可以通过各种客户端与Elasticsearch服务器进行交互,执行索引、搜索、聚合等数据操作,并以HTTP响应返回结果。

【一】Cookie

  • 是存在于浏览器的键值对,向服务端发起请求,需要携带cookie
  • 但是不安全
  • Cookie是一种存在于浏览器的键值对,用于在客户端和服务端之间传递数据。

    • 当用户访问一个网站时,网站服务器可以通过在响应头中设置Set-Cookie字段,将一个或多个Cookie发送给用户的浏览器。
    • 浏览器在接收到这些Cookie后,会将其保存起来。
  • 每次用户向同一个网站发起请求时,浏览器会自动将该网站对应的Cookie携带在请求头中发送给服务器。

    • 服务器可以通过读取这些Cookie来获取用户登录状态、保存用户的偏好设置或其他相关数据。
  • 尽管Cookie在一定程度上提供了方便性,但是也存在一些安全隐患。

    • 其中最主要的问题是Cookie可能被截获或篡改

      • 从而导致用户的敏感信息泄露或身份被盗用。
    • 因此,为了保护用户的隐私和安全

    • 网站通常会采取以下措施来加强Cookie的安全性:

      • 使用安全的传输协议

        • 通过使用HTTPS等安全的传输协议

        • 可以确保在传输过程中的数据不会被窃听或篡改。

      • 设置Secure标记

        • 通过在Set-Cookie字段中设置Secure属性

        • 可以告知浏览器只有在使用HTTPS连接时才发送该Cookie,这样就可以避免在非安全连接中传输敏感信息。

      • 设置HttpOnly标记

        • 通过在Set-Cookie字段中设置HttpOnly属性

        • 可以告知浏览器该Cookie仅限于服务器访问,无法通过JavaScript等脚本语言获取该Cookie的值,从而防止跨站脚本攻击(XSS)。

      • 限制Cookie的作用范围

        • 通过在Set-Cookie字段中设置Domain和Path属性

        • 可以限制Cookie只在特定的域名和路径下有效,避免被其他网站滥用。

      • 合理设置Cookie的过期时间

        • 通过设置Expires或Max-Age属性,可以控制Cookie的有效期限。一般来说
          • 对于需要用户登录的会话Cookie,应设置为会话级别,即关闭浏览器后自动删除;
          • 对于非会话Cookie,应设定合理的过期时间,避免Cookie长时间存在导致安全隐患。
  • 综上所述
    • 虽然Cookie在实现一些功能上提供了方便性,但其安全性问题仍需注意。
    • 网站开发者在使用Cookie时,应该遵循相关的安全规范,加强对用户隐私和数据的保护。
    • 同时,用户在使用网站时也要注意保护自己的信息安全,避免泄露敏感信息给不可信的网站。

【二】Session

  • 存在于服务器的键值对,存放在哪?
    • 存放在内存/文件/MySQL/Redis
  • 缺陷:
    • 如果用户量很大,存储需要耗费服务器资源
  • Session是一种存在于服务器端的键值对,用于存储用户的会话信息。

  • 与Cookie不同,Session数据不会存储在用户的浏览器中,而是存储在服务器端的某个地方。

  • Session的具体存储位置可以根据开发者的需求和技术选型而有所不同。

    • 以下是一些常见的存储位置:

      • 内存

        • 一些简单的Web服务器可以将Session数据存储在内存中。

        • 这种方式读写速度较快

          • 适用于小规模的应用

          • 但缺点是当服务器重启或崩溃时,所有的Session数据将丢失。

      • 文件系统

        • 另一种常见的方式是将Session数据存储在服务器的文件系统中。

        • 每个Session被保存为一个文件,文件名通常由Session ID决定,文件内容则为Session数据的键值对。

          • 这种方式适用于单服务器环境,并且可以保证Session数据持久化。

          • 然而,随着用户数量的增加,文件系统读写操作的性能可能会成为瓶颈。

      • 数据库(如MySQL)

        • 许多Web应用选择将Session数据存储在关系型数据库中,如MySQL。

        • 使用数据库作为Session存储

          • 优点是数据持久性好,并且可以支持较大规模的用户量。

          • 但相应地,读写数据库的开销也可能会增加一定的负载。

      • 缓存数据库(如Redis)

        • 一些高性能的Web应用会选择将Session数据存储在内存中的缓存数据库,如Redis。
        • Redis具有高速的读写性能和良好的扩展性,适合于处理大量请求和高并发场景。
  • 上述存储位置的选择应该根据实际需求和系统架构来决定。

  • 对于用户量很大的情况,存储Session数据可能会耗费服务器资源。

  • 为了解决这个问题,可以采取以下措施:

    • 分布式架构

      • 使用多台服务器来处理请求,并将Session数据进行分布式存储,从而提高性能和可扩展性。
    • 减小Session数据量

      • 只存储必要的会话信息,并避免存储大量的冗余数据,以减少服务器资源消耗。
    • 合理设置Session过期策略

      • 设置合理的Session过期时间,及时清理过期的Session数据,以释放服务器资源。
    • 使用缓存技术

      • 可以结合缓存数据库,如Redis,将热门的Session数据缓存在内存中,从而加快读写速度。

【三】Token

  • 就是个字符串
    • 既安全又有个人信息
    • 加密字符串会携带个人信息
  • 基于这种特性,契合了前后端分离
  • Token(令牌)是一个字符串,用于在前后端分离的应用中进行身份验证和授权。

  • Token本身是一种加密字符串,其中包含了一些关键信息,如用户的身份标识和其他相关的个人信息。

  • Token的设计兼具安全性和易用性的特点

    • 主要体现在以下方面:

      • 安全性

        • Token采用了加密算法进行生成和验证,使得其具有一定的安全性。

        • 加密后的字符串中已携带了用户的身份信息,并且被加密处理,防止了明文传输和篡改。

      • 隐私保护

        • Token将个人信息等敏感数据存储在服务器端,而不是在前端或浏览器中。

        • 这样可以降低用户信息泄露的风险。

        • 前端只需要在每次请求时携带Token,而无需传递用户的具体身份信息,保护了用户的隐私。

      • 前后端分离

        • Token的特性非常契合前后端分离架构。

        • 在传统的基于Session的身份验证中,服务器需要维护用户的会话状态,而在前后端分离中,服务器无需保存会话状态,而是通过验证Token的方式进行身份认证。

        • 这样可以提高服务器的可扩展性和并发处理能力,减轻了服务器的负担。

      • 易用性

        • Token的使用相对简单,前端在登录成功后会收到一个Token,并将其存储在客户端(如浏览器的Cookie或本地存储中)。
        • 后续的请求中,只需要在请求头中带上Token即可完成身份验证和授权。
        • 这种方式方便了前端的开发和维护,并且可以支持跨域访问。
  • 总体而言

    • Token作为一种身份验证和授权的机制,在前后端分离的架构中具有很好的适应性。
    • 它既保证了安全性,又降低了服务器负担,同时提供了方便的接口访问方式。
    • 然而,在设计和实现过程中,仍需考虑Token的生成算法、存储方式、过期时间等相关安全问题,以保证系统的整体安全性。

【四】JWT

JSON格式的Token字符串

  • JWT(JSON Web Token)是一种基于JSON格式的令牌字符串,用于在前后端分离的应用中进行身份验证和授权。

  • JWT由三部分组成:

    • 头部(Header)
    • 载荷(Payload)
    • 签名(Signature)。
  • 每一部分都使用Base64编码,通过点(.)进行分隔,形成一个完整的JWT字符串。

  • 具体结构如下:

xxxxx.yyyyy.zzzzz

【1】头部(Header)

  • 头部通常包含两部分信息,令牌的类型(typ)和使用的加密算法(alg)。
  • 例如,在一个JWT令牌中,头部可能如下所示:
{
  "typ": "JWT",
  "alg": "HS256"
}

【2】载荷(Payload)

  • 载荷是JWT的主要信息存放位置,可以包含一些自定义的声明(Claims),也可以使用一些预定义的声明。

  • 常见的预定义声明有:

    • iss:令牌发行者(Issuer)

    • sub:令牌主题(Subject)

    • aud:令牌受众(Audience)

    • exp:令牌过期时间(Expiration Time)

    • iat:令牌的签发时间(Issued At)

    • nbf:令牌的生效时间(Not Before)

    • jti:令牌的唯一标识(JWT ID)

  • 例如,一个包含用户ID和角色的JWT载荷可以如下所示:

{
  "userId": "123456",
  "role": "admin"
}

【3】签名(Signature)

  • 为了保证JWT的真实性和完整性,在服务器端对头部和载荷进行签名生成签名信息。
  • 签名需要使用一个密钥(秘钥),通常是一个只有服务器知道的字符串,用于验证令牌的合法性。

【4】校验

  • 在客户端使用JWT时,首先会将头部、载荷和签名信息按照一定规则组装成一个完整的JWT字符串,并将其发送到服务器进行验证。
  • 服务器会解析JWT,验证签名的正确性和有效期,以确定用户的身份和权限。

【5】总结

  • JWT作为一种基于JSON格式的令牌字符串,适用于前后端分离架构中的身份验证和授权。
  • 它具有的优点包括可扩展性、状态无关性和自包含性。
  • 但需要注意的是,在使用JWT时需注意安全性,包括选择合适的加密算法、保护密钥的安全性以及防止信息泄露等。

【补充】使用Django实现token功能

使用Django实现token功能 - 中间件

  • 在Django中实现Token功能可以使用中间件来处理请求和响应
  • 以下是一个简单的实现示例:
# my_app/middleware.py

from django.http import HttpResponseForbidden
from django.conf import settings

class TokenMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # 在请求处理之前执行的代码

        if not self.is_valid_token(request):
            return HttpResponseForbidden("Invalid token")

        response = self.get_response(request)

        # 在请求处理之后执行的代码

        return response

    def is_valid_token(self, request):
        # 根据实际情况从请求中获取Token,通常可以从请求头或请求参数中获取
        token = request.META.get('HTTP_AUTHORIZATION', '').split(' ')[1]

        # 验证Token的逻辑,可根据自己的认证方式进行实现
        # 例如,可以使用JWT库进行解析和验证
        try:
            # 对Token进行验证和解码
            # 如果验证通过,返回True,否则返回False
            decoded_token = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
            return True
        except jwt.exceptions.DecodeError:
            return False
  • 要使用此中间件,需要在Django的配置文件中进行相应的设置:
# settings.py

MIDDLEWARE = [
    # 其他中间件...
    'my_app.middleware.TokenMiddleware',
]
  • 在上述示例中
    • TokenMiddleware是一个自定义的中间件类,它在每个请求到达和离开Django视图之前都会被调用。
    • is_valid_token方法用于验证Token的有效性,可以根据实际需求进行修改。
    • 如果Token无效或不存在,中间件返回一个HttpResponseForbidden并拒绝请求。