短信邮件

eval

简介

eval() 是 Python 的一个内置函数,用于执行一个字符串表达式,并返回表达式的值。

基本语法

1
eval(expression, globals=None, locals=None)
  • expression: 字符串形式的 Python 表达式
  • globals (可选): 字典形式的全局命名空间
  • locals (可选): 字典形式的局部命名空间

基本用法

1
2
3
x = 1
result = eval('x + 1')
print(result) # 输出: 2

主要特点

  1. 执行字符串表达式:

    1
    print(eval('2 + 3 * 4'))  # 输出: 14
  2. 可以访问变量:

    1
    2
    a = 5
    print(eval('a * 2')) # 输出: 10
  3. 可以调用函数:

    1
    2
    3
    4
    def square(n):
    return n * n

    print(eval('square(5)')) # 输出: 25

安全性问题

eval() 可以执行任意 Python 代码,因此存在安全风险:

1
2
3
# 危险示例 - 不要在实际应用中使用这样的代码
user_input = input("请输入表达式: ")
print(eval(user_input)) # 用户可能输入恶意代码

限制执行环境

为了安全,可以限制 eval() 的执行环境:

1
2
3
4
5
6
7
8
from math import *
safe_dict = {'__builtins__': None} # 禁用内置函数
user_input = "sqrt(16)" # 假设这是用户输入

# 只允许访问 math 模块
safe_dict.update({k: v for k, v in globals().items() if k in ['sqrt', 'sin', 'cos']})

print(eval(user_input, safe_dict, safe_dict)) # 输出: 4.0

与 exec() 的区别

  • eval() 只能计算单个表达式并返回值
  • exec() 可以执行更复杂的代码块,但不返回值

替代方案

对于简单的表达式计算,可以考虑更安全的替代方案:

  1. 使用 ast.literal_eval() (只能计算字面量表达式):

    1
    2
    import ast
    print(ast.literal_eval("[1, 2, 3]")) # 输出: [1, 2, 3]
  2. 使用特定领域的解析器 (如数学表达式解析器)

简介

hashlib 是 Python 标准库中的一个模块,提供了多种安全哈希算法和消息摘要算法的实现。这些算法可用于数据完整性验证、密码存储、数字签名等安全相关场景。

主要特性

  1. 提供了多种哈希算法:MD5、SHA1、SHA224、SHA256、SHA384、SHA512 等
  2. 支持更安全的算法如 SHA3 和 BLAKE2(取决于 Python 版本)
  3. 使用简单统一的接口
  4. 支持增量哈希计算

常用哈希算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import hashlib

# MD5 (不推荐用于安全用途,仅用于遗留系统或校验)
md5 = hashlib.md5()

# SHA系列 (安全强度递增)
sha1 = hashlib.sha1() # 160位
sha256 = hashlib.sha256() # 256位
sha512 = hashlib.sha512() # 512位

# SHA3系列 (Python 3.6+)
sha3_256 = hashlib.sha3_256()
sha3_512 = hashlib.sha3_512()

# BLAKE2 (Python 3.6+)
blake2b = hashlib.blake2b()
blake2s = hashlib.blake2s()

基本使用方法

  1. 简单哈希计算

    1
    2
    3
    4
    5
    6
    7
    import hashlib

    # 计算字符串的SHA256哈希值
    data = "Hello, world!"
    hash_object = hashlib.sha256(data.encode())
    hex_digest = hash_object.hexdigest()
    print(hex_digest) # 输出16进制表示的哈希值
  2. 增量更新哈希

    1
    2
    3
    4
    hash_object = hashlib.sha256()
    hash_object.update(b"Hello, ")
    hash_object.update(b"world!")
    print(hash_object.hexdigest())
  3. 使用不同的输出格式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    hash_object = hashlib.sha256(b"Hello, world!")

    # 16进制字符串
    print(hash_object.hexdigest())

    # 二进制digest
    print(hash_object.digest())

    # 摘要长度(字节数)
    print(hash_object.digest_size)

    # 算法名称
    print(hash_object.name)

安全注意事项

  1. 不要使用 MD5 和 SHA1 用于密码存储或安全敏感用途,它们已被证明不安全
  2. 对于密码存储,应使用专门的密码哈希函数如 PBKDF2, bcrypt 或 scrypt
  3. Python 的 hashlib 也提供了 hashlib.pbkdf2_hmac() 用于密码哈希

密码哈希示例

1
2
3
4
5
6
7
8
9
10
11
import hashlib
import os

# 更安全的密码哈希方式
password = b"my_password"
salt = os.urandom(16) # 生成随机盐值
iterations = 100000 # 迭代次数

# 使用PBKDF2-HMAC-SHA256
key = hashlib.pbkdf2_hmac('sha256', password, salt, iterations)
print(key.hex())

新算法支持

在较新的 Python 版本中(3.6+),hashlib 还支持:

  • SHA3 算法系列
  • BLAKE2 算法系列
  • hashlib.scrypt() 函数(Python 3.6+)

urllib

  • 说明:
    • URI:统一资源标识符
    • URL:统一资源定位符,URI的一种形式,如:http://www.baidu.com:80?name=xiaoming&age=10
  • 示例:
    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
    from urllib.parse import urlencode

    d = {'name': 'dahua', 'age': 10}

    print(d)
    # 转换为:name=dahua&age=10
    print(urlencode(d))


    from urllib.parse import urlparse

    url = 'http://www.baidu.com:80/abc/def?page=3&size=5'
    # 解析出url中所有的参数
    # 结果:ParseResult(scheme='http', netloc='www.baidu.com:80', path='/abc/def', params='', query='page=3&size=5', fragment='')
    p = urlparse(url)
    print(p)
    # 请求参数
    print(p.query)


    from urllib.parse import parse_qs

    # 将url请求参数转换成字典
    # 结果:{'page': ['3'], 'size': ['5']}
    d = parse_qs(p.query)
    print(d)

http.client

  • 说明: 可以模拟浏览器发送http请求(是爬虫的基础)
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import http.client

    # 创建连接(相当于浏览器)
    connect = http.client.HTTPConnection('www.baidu.com')

    # 发送请求(GET、POST)
    connect.request(method='GET', url='https://www.baidu.com/')

    # 获取响应
    resp = connect.getresponse()

    # 打印响应内容,读取并解码
    print(resp.read().decode('utf-8'))

邮件发送

  • 说明: 在一个网站中经常使用邮件操作,如:激活、通知、等
  • smtp使用:
    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
    36
    37
    38
    39
    import os
    import smtplib

    # 将字符串转换为邮件的文本格式
    from email.mime.text import MIMEText

    # 邮箱服务器
    mail_server = 'smtp.163.com'

    # 用户名
    mail_user = '16666666@163.com'

    # 密码或授权码,为了不将密码公开,可以通过环境变量的形式获取
    mail_password = os.environ.get('MAIL_PASSWORD') or '123456'
    # mail_password = 'suyin'

    # 邮件消息
    message = '你好,欢迎注册xxx平台,激活请点击右边链接<a href="https://www.baidu.com/">百度一下</a>'
    # 将邮件字符串消息转换成邮件格式,若内容是HTML需要指定第二个参数为'html'
    message = MIMEText(message, 'html')

    # 设置主题
    message['Subject'] = '账户激活'
    # 设置发送人
    message['From'] = mail_user

    # 创建邮件对象
    mail = smtplib.SMTP(mail_server, 25)
    # 登录服务器
    mail.login(mail_user, mail_password)

    # 接收者,多个使用逗号隔开
    to = '155555555555@163.com'

    # 发送邮件
    mail.sendmail(mail_user, to, message.as_string())

    # 结束
    mail.quit()

短信发送

  • 说明: 注册验证码、通知消息、营销短息、…
  • 短信发送平台: 阿里、云之讯、秒滴、…
  • 示例: 秒滴(http://www.miaodiyun.com
    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    import time
    import hashlib
    import http.client
    from urllib.parse import urlencode

    # 请求地址
    url = 'https://api.miaodiyun.com/20150822/industrySMS/sendSMS'

    # 请求头
    headers = {'Content-type': 'application/x-www-form-urlencoded'}

    # 账户id
    accountSid = '8d7ec5467c27456b859d727268b62ca9'

    # auth token
    auth_token = '62438af2632f448c94b028a1641b3906'

    # 时间戳
    timestamp = time.strftime('%Y%m%d%H%M%S')

    sig = accountSid + auth_token + timestamp

    # 加密一下
    md = hashlib.md5()
    md.update(sig.encode('utf-8'))
    sig = md.hexdigest()

    # 模板参数
    yzm = '632881'
    t = '5'
    param = yzm + ',' + t

    # 表单数据
    form_data = {
    'accountSid': accountSid,
    'templateid': '1502437573',
    'to': '16657158725',
    'timestamp': timestamp,
    'sig': sig,
    'param': param
    }

    # 将字典转换为url参数形式
    form_data = urlencode(form_data)

    # 创建浏览器对象
    connect = http.client.HTTPConnection('api.miaodiyun.com')

    # 发送POST请求
    connect.request(method='POST', url=url, body=form_data, headers=headers)

    # 获取响应;
    resp = connect.getresponse()

    # 打印响应结果
    print(resp.read().decode('utf-8'))
本文结束 感谢您的阅读
正在加载今日诗词....