ForcePilot/backend/package/yuxi/channel/security/qr_image.py
Kris 849d21120f feat(channel/security): 新增完整安全工具模块
新增一系列安全相关功能:
1.  新增二维码生成工具,支持自定义参数导出图片/Base64/字节流
2.  新增HTML内容安全处理工具,包括标签剥离、转义、URL校验
3.  新增日志敏感信息脱敏工具,支持配置、字典、日志记录脱敏
4.  新增密钥管理运行时,支持从环境变量/文件加载密钥
5.  新增身份链接管理,支持多渠道身份绑定与解析
6.  新增SSRF防护工具,支持域名/IP校验与固定主机
7.  新增安全权限修复工具,修复文件目录权限与配置项
8.  新增外部内容安全处理,支持LLM特殊令牌剥离与注入检测
9.  新增认证限流工具,支持多维度限流与本地回环豁免
10. 新增配对管理工具,支持安全配对码生成与校验
11. 新增白名单管理工具,支持DM/群组/来源白名单校验
2026-05-21 10:32:57 +08:00

72 lines
1.9 KiB
Python

from __future__ import annotations
import base64
import io
import logging
logger = logging.getLogger(__name__)
QR_DEFAULT_BOX_SIZE = 10
QR_DEFAULT_BORDER = 4
QR_DEFAULT_FILL_COLOR = (0, 0, 0)
QR_DEFAULT_BACK_COLOR = (255, 255, 255)
def generate_qr_image(
data: str,
box_size: int = QR_DEFAULT_BOX_SIZE,
border: int = QR_DEFAULT_BORDER,
fill_color: str | tuple[int, int, int] = QR_DEFAULT_FILL_COLOR,
back_color: str | tuple[int, int, int] = QR_DEFAULT_BACK_COLOR,
):
import qrcode
from qrcode.image.styledpil import StyledPilImage
from qrcode.image.styles.colormasks import SolidFillColorMask
from qrcode.image.styles.moduledrawers import SquareModuleDrawer
qr = qrcode.QRCode(
version=None,
error_correction=qrcode.constants.ERROR_CORRECT_M,
box_size=box_size,
border=border,
)
qr.add_data(data)
qr.make(fit=True)
return qr.make_image(
image_factory=StyledPilImage,
module_drawer=SquareModuleDrawer(),
color_mask=SolidFillColorMask(
front_color=fill_color,
back_color=back_color,
),
)
def generate_qr_base64(
data: str,
box_size: int = QR_DEFAULT_BOX_SIZE,
border: int = QR_DEFAULT_BORDER,
fill_color: str = QR_DEFAULT_FILL_COLOR,
back_color: str = QR_DEFAULT_BACK_COLOR,
) -> str:
image = generate_qr_image(data, box_size, border, fill_color, back_color)
buf = io.BytesIO()
image.save(buf, format="PNG")
return base64.b64encode(buf.getvalue()).decode("utf-8")
def generate_qr_bytes(
data: str,
box_size: int = QR_DEFAULT_BOX_SIZE,
border: int = QR_DEFAULT_BORDER,
fill_color: str = QR_DEFAULT_FILL_COLOR,
back_color: str = QR_DEFAULT_BACK_COLOR,
) -> bytes:
image = generate_qr_image(data, box_size, border, fill_color, back_color)
buf = io.BytesIO()
image.save(buf, format="PNG")
return buf.getvalue()