当前位置:   article > 正文

python3_网络编程_app.router.add_get('/{method}/{source}/{songid}/{q

app.router.add_get('/{method}/{source}/{songid}/{quality}', handle)

网络编程

socket标准库

socket标准库是非常底层的接口库,socket是一种通用的网络编程接口
协议族Address Family
* AF_INET: IPV4
* AF_INET6: IPV6
* AF_UNIX: Unix Domain Socket,unix系统主机的socket
socket类型
* SOCK_STREAM: 面向连接的流socket, TCP协议
* SOCK_DGRAM: 无连接的datagram数据报socket, UDP协议


TCP编程

服务器

  1. 创建socket对象, sock= socket.socket(family, type)
  2. 绑定ip地址和端口, sock.bind(laddr: str,port: int)
  3. 开始监听, sock.listen()
  4. 接受accept连接,创建用于传输数据的socket对象
    s, addr(raddr,port) = sock.accept()
    阻塞,直到有连接创建,如果阻塞过程中被另一个线程close(),抛出OSError在非套接字上尝试操作
  5. 接收receive和发送send数据

    • recv(bufsize), 阻塞,直到从socket接收最大bufsize大小的data,返回bytes对象,如果remote end(远端) 正常closed, 函数返回b”, 强制关闭会抛异常; 如果在阻塞过程中,被另一个线程close(),抛出OSError”中止了一个连接”“, bufsize的大小最好是2的幂, 例如4096
    • send(data: bytes), 发送数据
    • close(), 关闭连接,

其他一些方法:

socket.makefile(mode='rw', buffering=None, *,encoding=None, errors=None,newline=None) 返回一个与该socket**相关联**的类文件对象,recv和send方法被read和write方法代替
socket.getpeername() 返回socket remote end地址,元组(rattr, port)
socket.getsockname() 返回socket 自己的地址,(lattr, port)
socket.setblocking(flag) flag为0,将socket设置为非阻塞模式,recv()不阻塞,没有数据就抛异常

客户端

  1. 创建socket,
  2. 创建连接 connect((raddr, port))
  3. 传输数据 ,send(),recv()
  4. 停止发送或接受数据, shutdown(flag), flag等于socket.SHUT_RD | SHUT_WR | SHUT_RDWR,关闭接收数据,关闭发送数据,全部关闭.关闭发送数据(SHUT_WR)后,对端每次recv立刻返回一个空bytes,
  5. close(),关闭连接,只是释放和连接相关的资源,要明确关闭连接,请先使用shutdown后再close
    close() releases the resource associated with a connection but does not necessarily close the connection immediately. If you want to close the connection in a timely fashion, call shutdown() before close().

UDP编程

服务端

  1. 创建socket, type=socket.SOCK_DGRAM
  2. bind((hostaddr, port)),绑定IP端口
  3. 接收数据recvfrom(),返回data和对端地址;
    发送数据sendto(bytes, (raddr, port))
    可以使用connect((raddr, port)),添加远端地址, 表示只接受指定地址的消息
  4. close(),关闭连接

客户端

  1. 新建socket, type=socket.SOCK_DGRAM
  2. 接收数据recvfrom(),返回data和对端地址; 发送数据sendto(bytes, (raddr, port))
    connect((raddr, port)),仅添加远端地址,只接受指定地址的消息
  3. close(),关闭连接

SocketServer

SocketServer简化了网络服务器的编写
4个同步类:TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer
2个Mixin类:ForkingMixIn和ThreadingMixIN,用来支持异步

class ForkingTCPServer(ForkingMixIn, TCPServer): pass
class ForkingUDPServer(ForkingMixIN, UDPServer): pass
class ThreadingUDPServer(ThreadingMixIN, UDPServer): pass
class ThreadingTCPServer(ThreadingMixIN, TCPServer): pass

fork创建多进程, thread是创建多线程
编程接口
socketserver.BaseServer(server_address, RequestHandlerClass)
RequestHandlerClass类必须是BaseRequestHandler类的子类,每一个请求会实例化对象,处理请求,拥有以下属性和方法:

self.request 是和客户端连接的socket对象
self.server 是server自己
self.client_address 是客户端地址
setup() 连接初始化
handle() 处理连接
finish() 连接清理

创建服务器步骤:

  1. 派生BaseRequestHandler子类,覆盖其中的,三个方法
  2. 实例化服务器类,传入服务端地址和请求处理类
  3. 启动服务器处理请求,处理一次handle_request()和永远处理serve_forever()
  4. 关闭服务器器,server_close()

server的方法和属性

address_family
socket_type
shutdown_request(self,request) shutdown并close一个独立的请求
close_request(self,request) close一个独立的请求
get_request(self) -> (request, client_addr) 获得一个独立的请求,会阻塞, 相对于accept
fileno(self) -> server.socket 的文件描述符, selector使用


zerorpc

是一个非常轻巧的, 跨语言的通信模块, 官网


异步编程

同步和异步
函数和方法被调用时,调用者是否直接得到最终的结果
直接得到就是同步调用,不直接得到就是异步调用,
阻塞和非阻塞
函数和方法被调用时,是否立即返回,
立即返回就是非阻塞,不立即返回就是阻塞
同步异步和阻塞非阻塞不相干

读取(read)IO两个阶段:
1. 数据准备阶段,内核从输入设备读取数据
2. 内核空间数据复制到用户进程缓冲区阶段

IO模型
同步IO模型包括: 阻塞IO, 非阻塞IO

  1. 同步阻塞IO,进程阻塞,直到拿到数据
  2. 同步非阻塞IO,进程在数据准备阶段不阻塞,但时不时会询问内核数据是否准备好,第二阶段还是会阻塞
  3. IO多路复用,同步非阻塞IO的增强,不用进程自己询问,而是实现一个应用程序接口,作为系统调用,同时监控多个IO请求(通过检查文件描述符状态),进程阻塞在接口处,一旦有一个数据可读,就通知进程来读取数据,即进入第二阶段,同样要阻塞.
    • select 数组,线性遍历O(n),有连接上限1024(x86)
    • poll 链表,线性遍历O(n),无连接上限
    • epoll 哈希表,时间通知机制,增加回调机制,O(1),无连接上限,fd一次拷贝
      异步IO模型: 进程不阻塞,内核完成数据准备后,直接将数据放入用户空间缓冲区,再通知进程进行后续操作

Python中的IO多路复用
select库,实现了select,poll系统调用,通用性好,操作系统都支持,但性能较差,部分实现了epoll

selectors库

实现了kqueque,epoll,devpoll,poll,select,
selectors.DefaultSelector会选择,当前系统性能最优的实现
编程步骤:

  1. 创建selector对象,DefaultSelector
  2. 创建文件对象sock,绑定端口,开启监听,设置非阻塞setblocking(False)
  3. 注册sock文件对象, selector.register(fileobj,event,data=None)返回一个SelectorKey对象,其实是一个namedtuple
    SelectorKey = namedtuple(‘SelectorKey’, [‘fileobj’, ‘fd’, ‘events’, ‘data’])
    fileobj文件对象,
    event事件selector.EVENT_READ(ob1) | selector.EVENT_WRITE(ob10),
    fd 文件描述符,
    data 回调函数或数据,当事件被触发时使用
  4. 开启selector监控循环(while True),
    ready = selector.select() -> 阻塞的,返回一个list,表示准备好的事件列表,每一个元素是一个二元组,(selectorkey,mask),mask表示发生的事件,1表示可读, 2表示可写, 3表示读写都可
    selectorkey存储了注册时的所有信息,fileobj,fd,events,data
  5. 反注册所有已注册fileobj,并关闭fileobj,fileobj存储在selector.get_map()中,最后关闭selector,

selector对象方法和属性
selector.get_map() -> dict, {fd:selectorkey, …}, key是文件描述符


aiohttp

aiohttp则是基于asyncio 模块实现的HTTP框架
可以使用aiohttp实现异步爬虫
例子:

from aiohttp import web
import asyncio
from aiohttp import ClientSession

async def handle(request: web.Request):
    print(request.match_info)
    print(request.query_string)
    return web.Response(text=request.match_info.get('id', '0000'), status=200)

app = web.Application()
app.router.add_get('/{id}', handle)
web.run_app(app, host='0.0.0.0', port=9977)

# client
async def get_html(url: str):
    async with ClientSession() as session:
        async with session.get(url) as res:
            print(res.status)
            text = await res.text()
            with open('bai', 'w', encoding='utf8') as f:
                f.write(text)

url = 'http://www.baidu.com'
loop = asyncio.get_event_loop()
loop.run_until_complete(get_html(url))
loop.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

另一个例子


WSGI协议 Web Server Gateway Interface

流程:
Browser—(http request)—>WSGI Server—(解包,封装eviron)—>WSGI App处理数据
Browser<—(http response body)—WSGI Server<—(http response body)—WSGI App
Browser<—(http status, response header)—WSGI App使用WSGI Server提供的方法(start_response)

WSGI服务器参考库wsgiref

from wsgiref.simple_server import make_server, demo_app
server = make_server(ip, port, demo_app)
try:
    server.serve_forever()    # 另server.handle_request()
except:
    server.shutdown()
    server.server_close()

def demo_app(environ,start_response):
from io import StringIO
    stdout = StringIO()
    print("Hello world!", file=stdout)
    print(file=stdout)
    h = sorted(environ.items())
    for k,v in h:
        print(k,'=',repr(v), file=stdout)
    start_response("200 OK", [('Content-Type','text/plain; charset=utf-8')])
    return [stdout.getvalue().encode("utf-8")]
# demo_app 接收两个参数
# environ: dict,保存的是http请求头部信息,key: REQUEST_METHOD, PATH_INFO, QUERY_STRING....
# start_response: 向Browser发送response status和header的方法,接收两个参数
#           start_response(status:str, response_header:二元组, exc_info=None)
# return必须是iterable, return要在start_response调用之后
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

linux测试命令: curl -I url 获得请求头
curl -X POST -d data -X指定方法,-d传输数据

urllib库解析QUERY_STRING
urllib.parse.parse_qs(environ.get(‘QUERY_STRING’))
webob environ的解析库

request = webob.Request(environ) #将environ解析成request对象
request属性headers/method/path/query_string/GET/POST/params
GET返回url中的数据, POST返回body中提交的数据, params返回所有数据
webob.multidict.MultiDict
多值字典,add(key, value), key不能为int, 相同的key可以共存,
md.getone(k)有且只有一个, md.getall()返回所有

res = webob.Response() # 实例化response对象,参数可以定义响应的status, body等
return res(environ, start_response) # response实例可调用,返回一个可迭代对象

# 使用 webob.dec装饰器实现app,一个request一个reponse
from webob.dec import wsgify
@wsgify
def app(request: webob.Request) -> webob.Response:
    res = webob.Response('body')
    return res         # return 可以是str,bytes,或者Response对象
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Flask框架实现

  1. 路由功能实现:
    将不同的(method, url_pattern, handler)注册到列表lst(有序), request到了后,遍历注册的列表,method匹配,并且url匹配就执行handler(request),返回response_body
    url匹配使用正则表达式,使用命名分组可以表示匹配字段含义,
    三部分:
    • class App, 使用__call__方法作为调用函数,接收request
    • class Router, 路由方法定义,路由信息收集
    • handlers, 定义及注册, 装饰器
  2. 路由分组,实现一级目录,即url前缀
    Route类实例添加前缀信息, 实例分别存放对应的注册信息, Route实例注册到App中, 遍历route实例
  3. 正则表达式的化简
    化简注册时使用的正则表达式为,对应的字段名和取值类型,{name:type},简化注册,同时提高匹配效率,可以将url匹配到的数据,转换成注册时设置的类型,传给handler处理
  4. 模板技术
    将数据填入html模板中作为response, 使用jinja2模块

    # index.html
    <ul>
        {% for id, name, age in userlist %}
        <li>{{loop.index}} {{id}} {{name}} {{age}}</li>
        {% endfor %}
        {{usercount}}}
    </ul>
    # template.py
    from jinja2 import Environment, PackageLoader, FileSystemLoader
    env = Environment(loader=FileSystemLoader('/web/templates')) # 添执行时主模块的相对路径,或绝对路径
    template = env.get_template('index.html') # 搜索env中loader文件夹下的index.html
    res = template.render(d)  # 渲染返回填好数据str, d为dict, key对应模板中的{{key}}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  5. 拦截器
    Preinterceptor / Postinterceptor
    全局interceptor, app中
    局部interceptor, router中
  6. json支持
    response = webob.Response(json=d) d为dict类型
  7. 模块化, 发布
    setup.py sdist

django

Django是采用MVC框架设计的开源WEB快速开发框架
自带ORM, Template, Form, Auth核心组件
Django 1.11版本同时支持python2和3
安装pip install django==1.11

管理程序django-admin :

/LIb/site-packages/django/bin/django-admin
django-admin startproject –help

创建项目:
django-admin startproject projectname .

个文件用途:
manage.py, 命令行工具, 应用创建, 数据库迁移等
blog/settings.py, 项目配置文件, 数据库参数等
blog/urls.py, URL路径映射配置
blog/wsgi, 定义WSGI接口信息, 一般无须改动

数据库配置

setting.py配置数据库连接

DATABASES={
    'ENGINE': 'django.db.backends.mysql'
    'NAME': 'blog',
    'USER': 'peijun',
    'PASSWORD': 'centos',
    'HOST': '192.168.10.129',
    'PORT': '3306'
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

安装数据库驱动, mysqlclient
pip install mysqlclient
windows下使用二进制包whl包

创建应用

python manage.py startapp appname
在setting.py中INSTALLED_APPS添加刚创建的appname应用
文件作用:

admin.py 管理站点模型的声明文件,用于后台管理
models.py 模型层model类定义
views.py 定义URL响应函数
migrations包 数据迁移文件生成目录
apps.py 应用的信息定义文件

路由, url函数
url(regex_pattern, view, kwargs=None, name=None)
url(r'^user/', include('user.urls')) 
**include**动态导入指定app下的urls模块, 二级匹配使用
  • 1
  • 2
  • 3
模型Model, Django ORM

django.db.models column类型:

AutoField
BooleanField
NullBooleanField
CharField
TextField
IntegerField/BigIntegerField
DecimalField 使用python的Decimal实例表示十进制浮点数, max_digits/decimal_places
FloatField python的Float实例表示浮点数
DateField 使用python的datetime.date实例表示的日期, auto_now/auto_now_add
TimeField 使用python的datetime.time实例表示的时间
DateTimeField 使用python的datetime.datetime实例表示的时间

字段选项

db_column 表中字段的名称, 未指定, 使用属性名
primary_key 设置主键
unique 设置唯一键
default 设施缺省值
null 设置null
blank Django表单验证中, 是否可以不填写, 默认为False
db_index 设置索引

关系类型字段Relationships
ForeignKey 表示many to one多对一, ForeignKey(mode_class, on_delete=models.CASCADE), 推荐外键属性使用小写的类名作为标识符
ManyToManyField 表示多对多
intermediary model,可以添加中间模块, 参数添加through='Membership', 构成多对多Unlike normal many-to-many fields, you can’t use add(), create(), or set() to create relationships:
OneToOneField 表示一对一
不设置主键, 默认添加主键表名_id
一对多时, 一端自动创建_id后缀属性
定义端访问,使用对象.定义属性名(一般使用modles)
相关端访问,使用对象.小写模型类名_set

创建Model类

from django.db import models
class User(models.Model):
    class Meta:     # metadate 设置表名,联合主键等, 不同应用的表名不要相同
        db_table = 'user'
    column1 = models.CharField(max_length=128)
  • 1
  • 2
  • 3
  • 4
  • 5

Meta “anything that’s not a field”
default_related_name related_query_name
db_table
ordering []
unique_together
indexs

模型操作:
模型类的objects属性, 是一个默认的manager, 用于和数据库交互, 也可以手动指定管理器
定义模型实例使用user = User()
user.save() INSERT
user.delet() DELETE
User.objects.create(name=’tom’) 创建记录并save()
模型类实例调用save(), delete()的时候,事务自动提交, save()和delete()都可以被覆盖, 增强功能
add() authors.add(author)
set() authors.set(authors)
remove()
clear() (https://docs.djangoproject.com/en/2.1/topics/db/queries/#additional-methods-to-handle-related-objects)
复制记录, 添加一条相同的记录, 仅主键不同
blog.pk = None; blog.save() # 多对多, 多对一是需要额外设置相关属性
querySet.update(content=’abc’) # 批量设置, 不会执行save(),
Making Queries

F 使用当前模块的字段值作为比较值(https://docs.djangoproject.com/en/2.1/topics/db/queries/#filters-can-reference-fields-on-the-model)

Field lookup
field__lookuptype=value

QuerySets Caching
limit 切片不会用的cache, 所有的元素都被迭代使用, 才会生成缓存
获取Related objects

QuerySet API reference 相关对象使用

查询集,QuerySet: 1.惰性求值, 只有查询集被使用是才查询数据库 2.拥有缓存,一个查询集可以被一个变量保存
返回查询集的方法叫做过滤器:

User.objects.all() :select * from User:
User.objects.all()[20:40] :limit offset查询集切片:
filter(column=’name’, pk=10) 筛选满足条件的记录
exclude()排除满足条件的记录 :where子句:
order_by(‘table_column’) :
Company.object.order_by(F(‘last_contacted’).desc(nulls_last=True))
null_last表示null排在最后
values() :记录用字典表示(column:value), 放入列表返回
pk总是表示主键
返回单值的方法:
get() 只返回一条记录, 多或者少都会抛异常
count() 返回查询总条数
first() 返回第一条记录
last() 返回最后一条记录
exists() 查询是否有数据, 有则返回True
in_bulk([1, 2], field_name=’pk’)
some_queryset.filter(pk=entry.pk).exists():

字段查询表达式(Field Lookup)

语法: filter(foreignmodes__colname__method=value)
exact: filter(isdeleted__exact=False) 严格等于, 可省略不写
contains: exclude(title__contains=”b”) 等价于 not like ‘%b%’
startswith: filter(title__startwith=”w”)
endswith:
isnull/isnotnull: 是否为None
iexact/icontains/istartwith/iendswith: 忽略大小写
in: filter(pk__in=[1,2,3])
year,month, day, week_day, hour, minute, second: 对日期类型指定具体时间

Q对象

from django.db.models import Q
Q类接收条件, Q对象可以使用&(and), |(or), ~(not)操作
filter函数,如果混用关键字参数和Q对象, Q对象必须位于关键字参数前面,所有参数条件都会被and到一起

迁移Migration

生成迁移文件
python manage.py makemigrations
执行迁移, 在数据库中生成表
python manage.py migrate

Django后台管理
  • 创建管理员
    python manage.py createsuperuser
  • 本地化 在settings.py中设置
    LANGUAGE_CODE = ‘zh-Hans’
    USE_TZ = True
    TIME_ZONE = ‘Asia/Shanghai’
  • 启动WEB Server
    python manage.py runserver
  • 登录后台管理
  • 注册应用模块 admin.py中添加
    admin.site.register(User)
模板 template

新建模板目录template, settings.py配置模板路径

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATES  = [{'DIRS': [os.path.join(BASE_DIR, 'templates')],},]
  • 1
  • 2

模板使用分为两步:

  • 加载模板, template = django.template.loader.get_template(‘index.html’)
  • 渲染
    context = django.template.RequestContext(request, {‘content’: ‘something’})
    return django.http.HttpResponse(template.render(context))
    快捷方式渲染
    from django.shortcuts import render
    return render(request, ‘indext.html’, {‘content’: ‘something’})
**DTL语法**Django Template Language
  • 变量: {{variable}}, 使用.点号访问容器内元素或对象内属性和方法, 调用方法不加括号, 变量未定义使用””
    模板标签
  • if/else标签:
    {% if condition %}
    …display
    {% elif condition %}
    …display
    {% else %}
    …display
    {% endif %}
    条件支持and, or, not
  • for标签
    {% for athlete in athlete_list %}
    {{athlete.name}}
    {% endfor %}
    for标签内变量:

  • forloop.counter 从1开始计数 forloop.revcounter 倒计数到1

  • forloop.counter0 从0开始计数 forloop.recounter0 倒计数到0
  • forloop.first 是否是循环的第一次 forloop.last 循环的最后一次
  • forloop.parentloop 嵌套循环时, 内层循环使用外层循环

{% for athlete in athlete_list reversed %} 反向迭代
{% ifequal val1 val2 %}{% ifnotequal val1 val2 %} 比较相等
{% csrf_token %} 跨站请求保护, 防止跨站攻击
CSRF(Cross-site request forgery) 跨站请求伪造, cookie授权, 伪造受信任用户
{# comment statement #} 单行注释
{% comment %} statement {% endcomment %} 多行注释

过滤器

在变量被显示前修改它, 语法{{variable|handler}}|两边没有空格
有的过滤器可以传参, :"para"

{{name|lower}}
{{name|first|upper}}
{{my_list|join:”,”}}
value|divisibleby:”2”|yesno:”True,False,None”, 能否被2整除, yesno可以只有两个参数true_false
value|add:”100”
|addslashes 在反斜杠和单引号或者双引号前面加上反斜杠
|length 容器的长度, str的长度
|default:”” 变量等价False则使用缺省值
|default_if_none:”” 变量为None则使用缺省值
|date:”n j Y” 格式化日期, n月j日Y年

处理请求函数views

第一个参数: request: HttpRequest
url中匹配到的分组也会依次按位置传入
获取request数据:

  • request.GET query字符串, 多值字典对象
  • request.body 请求方法为POST时, 获取数据
  • request.META 请求头中的数据
  • request.POST 表单提交的数据
返回数据

Response, JsonResponse,Django中有许多错误类, 实例可以作为view函数的返回值

from django.http import HttpResponseBadRequest, JsonResponse, HttpResponse
HttpResponse(status=401) # 添加状态码
  • 1
  • 2
认证
cookie和session

cookie存储session id, 每一次请求都被附带,
session id有过期的机制, 过期后session和cookie分别在服务端和客户端被清除
session信息会消耗服务器内存, 同时在多服务器部署时, 要考虑session共享的问题redis,memcached
memcached: 数据库查询缓存, 提高网站访问速度
cookie_session的使用

无session方案, JWT(Json WEB Token)

参考初步理解JWT并实践使用
服务器生成一个标识(代表客户端ID), 并对这个标识使用算法签名(防止数据被客户端篡改), 组成JWT数据
下次客户端将JWT数据发回, 服务端就可以确认是否是认证过的用户

pip install pyjwt
jwt_token = jwt.encode({'payload': 'id'}, key, 'HS256') -> bytes
  • 1
  • 2

key是编码和解码用的密钥, 尽可能复杂, settings.py 中的SECRET_KEY是一个强密码,导入使用
from django.conf import settings 导入setting模块

设置超时
"exp": int(datetime.datetime.now().timestamp()) + TOKEN_EXPIRE 加入payload, TOKEN_EXPIRE是超时时间

token以b'.'分为三部分,header(jwt,algorithm), payload, signature
前两部分使用base64编码的, 用base64解码后可以得到源信息, 所有jwt不是用来加密的, 仅保证数据不被修改

alg = algorithms.get_default_algorithms()\['HS256']
newkey = alg.prepare_key(SECRET_KEY)
signing_input, \_, _ = token.rpartition(b'.')
sign = alg.sign(signing_input, newkey)
signature = base64.urlsafe_b64encode(sign)
  • 1
  • 2
  • 3
  • 4
  • 5

生成token的过程:
前面两部分字典转换成json格式的字符串(注意冒号两边没有空格),再encode成bytes, 再用base64编码,
header和payload两部分由b'.'相连, 再有这个部分和密钥key生成的签名(bytes), 再用base64编码,与前面相连

jwt解码

payload = jwt.decode(jwt_token, key, algorithms=\['HS256']) -> payload_data
  • 1

RSA是公开的密钥密码体制, 有PK和SK, 非对称算法, 所有人都可以使用PK加密,只有拥有SK,才能对消息解密. 对极大整数做因数分解的难度决定了RSA算法的可靠性.
HMAC数字签名, 对称算法, 一个密钥和一个消息作为输入, 输入一个签名
消息双方都有密钥, 用于验证连接是否合法, (发送随机数, 双方算出结果, 验证)
或者用于确保消息不被篡改, (消息和签名绑定)

密码加密bcrypt

慢算法, 耗时长, 不同密码使用不同盐

bcrypt.gensalt() 生成盐
bcrypt.hashpw(password, salt) 生成加密密钥
password是bytes, 密钥由盐决定, 生成的加密密钥也是bytes, 盐就是前22个字节
bcrypt.checkpw(password, enci_password)


缓存Django-Redis

文档

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/487280
推荐阅读
相关标签
  

闽ICP备14008679号