Weibw's World Weibw's World
首页
  • HTML
  • Python

    • Python基础知识
    • Python CookBook第三版
    • Flask
  • MySQL

    • MySQL基础知识
    • MySQL调优
    • MySQL面试题
算法
  • FineReport
  • Kettle
  • Git
  • 微信公众号文章
  • 优秀博客文章
  • 其他
收藏夹
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Weibw

一个没有梦想的咸鱼
首页
  • HTML
  • Python

    • Python基础知识
    • Python CookBook第三版
    • Flask
  • MySQL

    • MySQL基础知识
    • MySQL调优
    • MySQL面试题
算法
  • FineReport
  • Kettle
  • Git
  • 微信公众号文章
  • 优秀博客文章
  • 其他
收藏夹
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 《Flask》

  • 《Python Cookbook》第三版

    • 第一章:数据结构与算法

    • 第二章:字符串和文本

    • 第三章:数字日期和时间

    • 第四章:迭代器与生成器

    • 第五章:文件与IO

    • 第六章:数据编码和处理

    • 第七章:函数

    • 第八章:类与对象

    • 第九章:元编程

    • 第十章:模块与包

    • 第十一章:网络与Web编程

      • 作为客户端与HTTP服务交互
      • 创建TCP服务器
      • 创建UDP服务器
      • 通过CIDR地址生成对应的IP地址集
      • 创建一个简单的REST接口
      • 通过XML-RPC实现简单的远程调用
      • 在不同的Python解释器之间交互
      • 实现远程方法调用
      • 简单的客户端认证
        • 问题
        • 解决方案
        • 讨论
      • 在网络服务中加入SSL
      • 进程间传递Socket文件描述符
      • 理解事件驱动的IO
      • 发送与接收大型数组
    • 第十二章:并发编程

    • 第十三章:脚本编程与系统管理

    • 第十四章:测试、调试和异常

    • 第十五章:C语言扩展

  • Python基础

  • Python
  • 《Python Cookbook》第三版
  • 第十一章:网络与Web编程
weibw
2022-01-18

简单的客户端认证

# 问题

你想在分布式系统中实现一个简单的客户端连接认证功能,又不想像SSL那样的复杂。

# 解决方案

可以利用 hmac 模块实现一个连接握手,从而实现一个简单而高效的认证过程。下面是代码示例:

import hmac
import os

def client_authenticate(connection, secret_key):
    '''
    Authenticate client to a remote service.
    connection represents a network connection.
    secret_key is a key known only to both client/server.
    '''
    message = connection.recv(32)
    hash = hmac.new(secret_key, message)
    digest = hash.digest()
    connection.send(digest)

def server_authenticate(connection, secret_key):
    '''
    Request client authentication.
    '''
    message = os.urandom(32)
    connection.send(message)
    hash = hmac.new(secret_key, message)
    digest = hash.digest()
    response = connection.recv(len(digest))
    return hmac.compare_digest(digest,response)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

基本原理是当连接建立后,服务器给客户端发送一个随机的字节消息(这里例子中使用了 os.urandom() 返回值)。 客户端和服务器同时利用hmac和一个只有双方知道的密钥来计算出一个加密哈希值。然后客户端将它计算出的摘要发送给服务器, 服务器通过比较这个值和自己计算的是否一致来决定接受或拒绝连接。摘要的比较需要使用 hmac.compare_digest() 函数。 使用这个函数可以避免遭到时间分析攻击,不要用简单的比较操作符(==)。 为了使用这些函数,你需要将它集成到已有的网络或消息代码中。例如,对于sockets,服务器代码应该类似下面:

from socket import socket, AF_INET, SOCK_STREAM

secret_key = b'peekaboo'
def echo_handler(client_sock):
    if not server_authenticate(client_sock, secret_key):
        client_sock.close()
        return
    while True:

        msg = client_sock.recv(8192)
        if not msg:
            break
        client_sock.sendall(msg)

def echo_server(address):
    s = socket(AF_INET, SOCK_STREAM)
    s.bind(address)
    s.listen(5)
    while True:
        c,a = s.accept()
        echo_handler(c)

echo_server(('', 18000))

Within a client, you would do this:

from socket import socket, AF_INET, SOCK_STREAM

secret_key = b'peekaboo'

s = socket(AF_INET, SOCK_STREAM)
s.connect(('localhost', 18000))
client_authenticate(s, secret_key)
s.send(b'Hello World')
resp = s.recv(1024)
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
27
28
29
30
31
32
33
34
35

# 讨论

hmac 认证的一个常见使用场景是内部消息通信系统和进程间通信。 例如,如果你编写的系统涉及到一个集群中多个处理器之间的通信, 你可以使用本节方案来确保只有被允许的进程之间才能彼此通信。 事实上,基于 hmac 的认证被 multiprocessing 模块使用来实现子进程直接的通信。

还有一点需要强调的是连接认证和加密是两码事。 认证成功之后的通信消息是以明文形式发送的,任何人只要想监听这个连接线路都能看到消息(尽管双方的密钥不会被传输)。

hmac认证算法基于哈希函数如MD5和SHA-1,关于这个在IETF RFC 2104中有详细介绍。

编辑 (opens new window)
上次更新: 2023/10/13, 17:39:25
实现远程方法调用
在网络服务中加入SSL

← 实现远程方法调用 在网络服务中加入SSL→

最近更新
01
牛客网非技术快速入门SQL练习题
03-08
02
其他日常SQL题
03-07
03
用户与权限管理
03-05
更多文章>
Theme by Vdoing | Copyright © 2021-2023 | Weibw | 辽ICP备18015889号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式