详细介绍:Redis多租户资源隔离方案:基于ACL的权限控制与管理

news/2025/10/27 21:13:03/文章来源:https://www.cnblogs.com/gccbuaa/p/19170179

Redis多租户资源隔离方案:基于ACL的权限控制与管理

  • 一、多租户架构设计
    • 1.1 核心挑战与解决方案
    • 1.2 整体架构设计
    • 1.3 权限模型设计
  • 二、Redis ACL详解
    • 2.1 ACL语法规则
      • 2.1.1 基本权限类别
      • 2.1.2 命令类别说明
    • 2.2 ACL用户管理命令
      • 2.2.1 用户管理操作
      • 2.2.2 完整ACL配置示例
  • 三、多租户ACL实战方案
    • 3.1 租户权限模板设计
    • 3.2 ACL管理服务实现
    • 3.3 租户连接池管理
  • 四、完整工作流程
    • 4.1 租户生命周期管理
    • 4.2 权限验证流程
    • 4.3 完整示例代码
  • 五、高级特性与优化
    • 5.1 资源配额管理
    • 5.2 监控与审计
  • 六、生产环境部署
    • 6.1 Redis配置优化
    • 6.2 高可用架构
    • 6.3 备份与恢复策略
  • 七、安全最佳实践
    • 7.1 安全加固措施
    • 7.2 合规性与审计

一、多租户架构设计

1.1 核心挑战与解决方案

在多租户环境中,多个租户共享同一个Redis实例或集群,主要面临以下挑战:

挑战传统方案缺陷ACL解决方案
数据安全单一密码,权限过大每个租户独立ACL账号,最小权限原则
资源隔离无隔离,相互影响Key空间隔离,命令权限控制
性能保障无限制,相互抢占内存、连接数、命令频率限制
运维管理手动操作,易出错自动化ACL生命周期管理

1.2 整体架构设计

监控审计
Redis ACL命名空间
ACL操作日志
资源使用监控
安全审计追踪
Key模式: tenant_a:*
Redis实例/集群
Key模式: tenant_b:*
Key模式: tenant_c:*
租户A应用
ACL用户: tenant_a
租户B应用
ACL用户: tenant_b
租户C应用
ACL用户: tenant_c

1.3 权限模型设计

租户
ACL用户
权限规则
Key模式权限
命令权限
资源限制
读写权限
Key模式匹配
允许的命令
禁止的命令
内存限制
连接数限制
命令频率限制

二、Redis ACL详解

2.1 ACL语法规则

Redis ACL使用一套简洁的语法来定义权限规则:

2.1.1 基本权限类别

# 权限开关
on|off           # 账户启用/禁用
+<command>       # 允许命令-<command>       # 禁止命令+@<category>     # 允许命令类别-@<category>     # 禁止命令类别allcommands      # 所有命令(危险)nocommands       # 无命令权限# Key模式权限~<pattern>       # 可访问的Key模式*<pattern>       # 所有Key模式(危险)resetkeys        # 重置Key模式# 资源限制><password>      # 设置密码<<password>      # 移除密码#<hashedpassword> # 设置哈希密码%R~<pattern>     # Pub/Sub通道模式%W~<pattern>     # 写命令Key模式

2.1.2 命令类别说明

# 常用命令类别
@admin          # 管理命令(CONFIG, SHUTDOWN等)
@dangerous      # 危险命令(FLUSHALL, KEYS等)
@read           # 只读命令(GET, LRANGE等)
@write          # 写命令(SET, LPUSH等)
@string         # 字符串命令
@list           # 列表命令
@set            # 集合命令
@sortedset      # 有序集合命令
@hash           # 哈希命令
@pubsub         # 发布订阅命令
@transaction    # 事务命令
@connection     # 连接命令
@scripting      # Lua脚本命令

2.2 ACL用户管理命令

2.2.1 用户管理操作

# 查看所有用户
ACL LIST
# 查看特定用户
ACL GETUSER username
# 创建用户
ACL SETUSER username [rules...]
# 删除用户
ACL DELUSER username
# 用户列表
ACL USERS
# 生成密码哈希
ACL GENPASS
# 保存ACL配置
ACL SAVE

2.2.2 完整ACL配置示例

# 创建只读用户,只能访问tenant_a:*
ACL SETUSER tenant_a_ro on >password123 ~tenant_a:* +@read -@dangerous
# 创建读写用户,有限命令集
ACL SETUSER tenant_a_rw on >password456 ~tenant_a:* +get +set +hget +hset +lrange +lpush -@admin
# 创建管理用户,所有权限但限制Key范围
ACL SETUSER tenant_a_admin on >password789 ~tenant_a:* +@all -@dangerous

三、多租户ACL实战方案

3.1 租户权限模板设计

根据不同租户需求,设计多级权限模板:

# acl_templates.py
class ACLTemplates:
"""ACL权限模板库"""
# 只读用户模板
READ_ONLY = {
'keys': ['~{tenant}:*'],
'commands': ['+@read', '-@dangerous', '-flushdb', '-flushall'],
'channels': ['%R~{tenant}:*'],
'limits': ['-keys 10000']  # 限制Key数量
}
# 读写用户模板
READ_WRITE = {
'keys': ['~{tenant}:*'],
'commands': [
'+@read', '+@write', '+@string', '+@list', '+@hash', '+@set',
'+@sortedset', '-@admin', '-@dangerous', '-flushdb', '-flushall',
'-keys', '-config'
],
'channels': ['%R~{tenant}:*', '%W~{tenant}:*'],
'limits': ['-keys 50000', '-memory 100mb']
}
# 管理用户模板
ADMIN = {
'keys': ['~{tenant}:*'],
'commands': ['+@all', '-flushdb', '-flushall', '-shutdown'],
'channels': ['%R~*', '%W~*'],
'limits': ['-keys 100000', '-memory 500mb']
}
# 应用特定模板
CACHE_APP = {
'keys': ['~{tenant}:cache:*'],
'commands': ['+get', '+set', '+del', '+exists', '+expire', '+ttl'],
'limits': ['-keys 1000000', '-memory 1gb']
}
@classmethod
def get_template(cls, template_name, tenant_id):
"""根据模板名称和租户ID生成ACL规则"""
template = getattr(cls, template_name.upper())
rules = []
# 处理Key模式
for key_pattern in template['keys']:
rules.append(key_pattern.format(tenant=tenant_id))
# 处理命令
rules.extend(template['commands'])
# 处理限制
rules.extend(template.get('limits', []))
return rules

3.2 ACL管理服务实现

# acl_manager.py
import redis
import hashlib
import logging
from typing import List, Dict
class RedisACLManager:
"""Redis ACL管理器"""
def __init__(self, redis_host: str, redis_port: int = 6379,
admin_password: str = None):
self.redis_host = redis_host
self.redis_port = redis_port
self.admin_client = redis.Redis(
host=redis_host, port=redis_port,
password=admin_password, decode_responses=True
)
self.logger = logging.getLogger(__name__)
def create_tenant_user(self, tenant_id: str, password: str,
template_name: str = 'READ_WRITE') -> bool:
"""创建租户用户"""
try:
# 生成ACL规则
acl_rules = ACLTemplates.get_template(template_name, tenant_id)
# 构建ACL SETUSER命令
username = f"tenant_{tenant_id}"
command_parts = [f"ACL SETUSER {username} on >{password}"]
command_parts.extend(acl_rules)
full_command = ' '.join(command_parts)
self.logger.info(f"Creating user {username}: {full_command}")
# 执行ACL命令
result = self.admin_client.execute_command(full_command)
# 保存ACL配置
self.admin_client.execute_command("ACL SAVE")
self.logger.info(f"Successfully created user {username}")
return True
except Exception as e:
self.logger.error(f"Failed to create user {tenant_id}: {e}")
return False
def delete_tenant_user(self, tenant_id: str) -> bool:
"""删除租户用户"""
try:
username = f"tenant_{tenant_id}"
result = self.admin_client.execute_command(f"ACL DELUSER {username}")
self.admin_client.execute_command("ACL SAVE")
self.logger.info(f"Successfully deleted user {username}")
return True
except Exception as e:
self.logger.error(f"Failed to delete user {tenant_id}: {e}")
return False
def list_tenant_users(self) -> List[Dict]:
"""列出所有租户用户"""
try:
users = self.admin_client.execute_command("ACL USERS")
tenant_users = []
for username in users:
if username.startswith('tenant_'):
user_info = self.admin_client.execute_command(f"ACL GETUSER {username}")
tenant_users.append({
'username': username,
'rules': user_info
})
return tenant_users
except Exception as e:
self.logger.error(f"Failed to list users: {e}")
return []
def validate_tenant_access(self, tenant_id: str, password: str) -> bool:
"""验证租户访问权限"""
try:
username = f"tenant_{tenant_id}"
test_client = redis.Redis(
host=self.redis_host, port=self.redis_port,
username=username, password=password, decode_responses=True
)
# 测试基本操作权限
test_key = f"{tenant_id}:test:access"
test_client.set(test_key, "test", ex=10)  # 10秒过期
value = test_client.get(test_key)
test_client.delete(test_key)
return value == "test"
except Exception as e:
self.logger.error(f"Access validation failed for {tenant_id}: {e}")
return False
def update_tenant_limits(self, tenant_id: str, new_limits: Dict) -> bool:
"""更新租户资源限制"""
try:
username = f"tenant_{tenant_id}"
# 获取当前用户规则
current_rules = self.admin_client.execute_command(f"ACL GETUSER {username}")
# 构建新规则(简化实现)
# 实际应该解析现有规则并更新限制部分
update_command = f"ACL SETUSER {username} reset"
result = self.admin_client.execute_command(update_command)
# 重新应用规则(需要完整规则集)
# 这里简化处理,实际应该更精细地更新
self.admin_client.execute_command("ACL SAVE")
return True
except Exception as e:
self.logger.error(f"Failed to update limits for {tenant_id}: {e}")
return False

3.3 租户连接池管理

# connection_pool.py
import redis
from threading import local
class TenantAwareConnectionPool:
"""租户感知的连接池"""
def __init__(self, redis_host: str, redis_port: int = 6379):
self.redis_host = redis_host
self.redis_port = redis_port
self._pools = {}  # 租户ID到连接池的映射
self._local = local()
def get_connection_pool(self, tenant_id: str, password: str) -> redis.ConnectionPool:
"""获取或创建租户专用的连接池"""
pool_key = f"{tenant_id}:{password}"
if pool_key not in self._pools:
username = f"tenant_{tenant_id}"
self._pools[pool_key] = redis.ConnectionPool(
host=self.redis_host,
port=self.redis_port,
username=username,
password=password,
max_connections=20,  # 每个租户最大连接数
decode_responses=True
)
return self._pools[pool_key]
def get_redis_client(self, tenant_id: str, password: str) -> redis.Redis:
"""获取租户专用的Redis客户端"""
pool = self.get_connection_pool(tenant_id, password)
return redis.Redis(connection_pool=pool)
class MultiTenantRedisClient:
"""多租户Redis客户端封装"""
def __init__(self, redis_host: str, redis_port: int):
self.connection_pool = TenantAwareConnectionPool(redis_host, redis_port)
def execute(self, tenant_id: str, password: str,
command: str, *args, **kwargs):
"""执行Redis命令"""
client = self.connection_pool.get_redis_client(tenant_id, password)
try:
# 自动添加租户前缀到Key
if command in ['get', 'set', 'hget', 'hset', 'lpush', 'rpush']:
if args and not args[0].startswith(f"{tenant_id}:"):
args = (f"{tenant_id}:{args[0]}",) + args[1:]
method = getattr(client, command)
return method(*args, **kwargs)
except redis.exceptions.AuthenticationError:
raise PermissionError(f"Authentication failed for tenant {tenant_id}")
except redis.exceptions.ResponseError as e:
if 'no permission' in str(e).lower():
raise PermissionError(f"Permission denied for command {command}")
raise
# 常用命令的便捷方法
def get(self, tenant_id: str, password: str, key: str):
return self.execute(tenant_id, password, 'get', key)
def set(self, tenant_id: str, password: str, key: str, value: str, ex=None):
return self.execute(tenant_id, password, 'set', key, value, ex=ex)
def hgetall(self, tenant_id: str, password: str, key: str):
return self.execute(tenant_id, password, 'hgetall', key)

四、完整工作流程

4.1 租户生命周期管理

4.2 权限验证流程

无效
有效
无权限
有权限
不匹配
匹配
租户请求
验证租户凭证
返回认证错误
创建租户连接
执行Redis命令
ACL权限检查
返回权限错误
执行命令
Key模式验证
返回Key错误
执行成功
记录审计日志

4.3 完整示例代码

# multi_tenant_demo.py
from acl_manager import RedisACLManager
from connection_pool import MultiTenantRedisClient
def demo_multi_tenant_workflow():
"""演示多租户完整工作流程"""
# 初始化ACL管理器(使用管理员权限)
acl_manager = RedisACLManager(
redis_host='localhost',
redis_port=6379,
admin_password='admin_password'
)
# 初始化多租户客户端
redis_client = MultiTenantRedisClient('localhost', 6379)
# 1. 创建两个租户
tenant_a = "company_a"
tenant_b = "company_b"
print("=== 创建租户 ===")
acl_manager.create_tenant_user(tenant_a, "password_a", "READ_WRITE")
acl_manager.create_tenant_user(tenant_b, "password_b", "READ_ONLY")
# 2. 验证租户访问
print("\n=== 验证租户访问 ===")
assert acl_manager.validate_tenant_access(tenant_a, "password_a")
assert acl_manager.validate_tenant_access(tenant_b, "password_b")
print("✓ 租户访问验证通过")
# 3. 租户A执行读写操作
print("\n=== 租户A操作演示 ===")
try:
redis_client.set(tenant_a, "password_a", "user:1001", "Alice")
redis_client.set(tenant_a, "password_a", "cache:session", "abc123", ex=3600)
value = redis_client.get(tenant_a, "password_a", "user:1001")
print(f"租户A读取数据: {value}")
except Exception as e:
print(f"租户A操作错误: {e}")
# 4. 租户B尝试写操作(应该失败)
print("\n=== 租户B写操作演示(应失败) ===")
try:
redis_client.set(tenant_b, "password_b", "user:2001", "Bob")
print("租户B写操作成功(这不应该发生)")
except PermissionError as e:
print(f"✓ 租户B写操作正确被拒绝: {e}")
# 5. 租户B读操作(应该成功)
print("\n=== 租户B读操作演示 ===")
try:
# 租户B不能读取租户A的数据
value = redis_client.get(tenant_b, "password_b", "company_a:user:1001")
print(f"租户B读取租户A数据: {value}")
except Exception as e:
print(f"✓ 租户B不能读取租户A数据: {e}")
# 6. 列出所有租户
print("\n=== 当前租户列表 ===")
tenants = acl_manager.list_tenant_users()
for tenant in tenants:
print(f"租户: {tenant['username']}")
# 7. 清理演示数据
print("\n=== 清理演示数据 ===")
acl_manager.delete_tenant_user(tenant_a)
acl_manager.delete_tenant_user(tenant_b)
print("✓ 演示完成")
if __name__ == "__main__":
demo_multi_tenant_workflow()

五、高级特性与优化

5.1 资源配额管理

# quota_manager.py
import time
from typing import Dict
class TenantQuotaManager:
"""租户资源配额管理"""
def __init__(self, acl_manager: RedisACLManager):
self.acl_manager = acl_manager
self.quotas = {}  # 租户配额配置
self.usage = {}   # 租户使用情况
def set_quota(self, tenant_id: str, quota_config: Dict):
"""设置租户配额"""
self.quotas[tenant_id] = {
'max_memory': quota_config.get('max_memory', 100 * 1024 * 1024),  # 100MB默认
'max_keys': quota_config.get('max_keys', 10000),
'max_connections': quota_config.get('max_connections', 20),
'commands_per_second': quota_config.get('commands_per_second', 1000)
}
# 更新ACL限制
acl_limits = [
f"-memory {quota_config.get('max_memory', 100 * 1024 * 1024)}",
f"-keys {quota_config.get('max_keys', 10000)}"
]
# 这里需要调用ACL管理器更新用户规则
self.update_acl_limits(tenant_id, acl_limits)
def check_quota(self, tenant_id: str, operation: str) -> bool:
"""检查租户配额"""
if tenant_id not in self.quotas:
return True
quota = self.quotas[tenant_id]
usage = self.usage.get(tenant_id, {})
# 内存使用检查
if usage.get('memory', 0) > quota['max_memory']:
return False
# Key数量检查
if usage.get('keys', 0) > quota['max_keys']:
return False
# 命令频率检查(简单实现)
current_minute = int(time.time() / 60)
minute_key = f"cmd_rate:{tenant_id}:{current_minute}"
if usage.get(minute_key, 0) > quota['commands_per_second'] * 60:
return False
return True
def record_usage(self, tenant_id: str, operation: str, cost: int = 1):
"""记录租户资源使用"""
if tenant_id not in self.usage:
self.usage[tenant_id] = {}
current_minute = int(time.time() / 60)
minute_key = f"cmd_rate:{tenant_id}:{current_minute}"
self.usage[tenant_id][minute_key] = \
self.usage[tenant_id].get(minute_key, 0) + cost

5.2 监控与审计

# monitoring.py
import json
import time
from datetime import datetime
class TenantMonitoring:
"""租户监控与审计"""
def __init__(self, redis_client):
self.redis_client = redis_client
self.audit_log_key = "tenant_audit_log"
def log_operation(self, tenant_id: str, operation: str,
key: str, success: bool, details: Dict = None):
"""记录操作审计日志"""
log_entry = {
'timestamp': datetime.utcnow().isoformat(),
'tenant_id': tenant_id,
'operation': operation,
'key': key,
'success': success,
'details': details or {}
}
# 使用Redis Streams记录审计日志
self.redis_client.xadd(
self.audit_log_key,
log_entry,
maxlen=10000  # 保留最近10000条日志
)
def get_tenant_metrics(self, tenant_id: str) -> Dict:
"""获取租户指标"""
# 统计Key数量
pattern = f"{tenant_id}:*"
keys_count = len(self.redis_client.keys(pattern))
# 统计内存使用(近似值)
total_memory = 0
sample_keys = self.redis_client.keys(pattern)[:100]  # 采样100个Key
for key in sample_keys:
try:
memory = self.redis_client.memory_usage(key)
total_memory += memory or 0
except:
pass
# 估算总内存
estimated_memory = total_memory * max(1, keys_count / 100)
return {
'keys_count': keys_count,
'estimated_memory': estimated_memory,
'last_activity': datetime.utcnow().isoformat()
}

六、生产环境部署

6.1 Redis配置优化

# redis_multitenant.conf
# ACL配置
aclfile /etc/redis/users.acl
acllog-max-len 1000
# 内存限制
maxmemory 16gb
maxmemory-policy allkeys-lru
# 监控配置
latency-monitor-threshold 100
slowlog-log-slower-than 10000
slowlog-max-len 128
# 安全配置
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command CONFIG ""
# 性能优化
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
set-max-intset-entries 512

6.2 高可用架构

应用服务器
ACL管理器
租户A应用
租户B应用
租户C应用
负载均衡器
Redis主节点
Redis从节点
ACL配置同步
监控代理
监控中心
告警系统

6.3 备份与恢复策略

# backup_manager.py
import json
import subprocess
from datetime import datetime
class ACLBackupManager:
"""ACL配置备份管理"""
def __init__(self, acl_manager: RedisACLManager, backup_dir: str):
self.acl_manager = acl_manager
self.backup_dir = backup_dir
def backup_acl_config(self) -> str:
"""备份ACL配置"""
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_file = f"{self.backup_dir}/acl_backup_{timestamp}.json"
# 获取所有用户配置
users = self.acl_manager.list_tenant_users()
backup_data = {
'timestamp': timestamp,
'users': users
}
with open(backup_file, 'w') as f:
json.dump(backup_data, f, indent=2)
return backup_file
def restore_acl_config(self, backup_file: str) -> bool:
"""恢复ACL配置"""
try:
with open(backup_file, 'r') as f:
backup_data = json.load(f)
# 清空现有ACL配置(保留默认用户)
# 重新创建所有租户用户
for user_data in backup_data['users']:
# 解析用户规则并重新创建
# 这里需要根据备份数据重建用户
pass
return True
except Exception as e:
print(f"恢复失败: {e}")
return False

七、安全最佳实践

7.1 安全加固措施

  1. 密码策略
def validate_password_strength(password: str) -> bool:
"""验证密码强度"""
if len(password) < 12:
return False
if not any(c.isupper() for c in password):
return False
if not any(c.islower() for c in password):
return False
if not any(c.isdigit() for c in password):
return False
if not any(c in '!@#$%^&*' for c in password):
return False
return True
  1. 定期轮换
def rotate_tenant_password(self, tenant_id: str) -> str:
"""轮换租户密码"""
new_password = self.generate_secure_password()
# 更新ACL密码
# 通知应用更新配置
return new_password
  1. 最小权限原则
    • 每个租户只授予必要的命令权限
    • 严格限制Key模式访问范围
    • 定期审计权限使用情况

7.2 合规性与审计

# compliance_checker.py
class ComplianceChecker:
"""合规性检查"""
def check_acl_compliance(self) -> Dict:
"""检查ACL合规性"""
issues = []
users = self.acl_manager.list_tenant_users()
for user in users:
issues.extend(self.check_user_compliance(user))
return {
'total_users': len(users),
'issues_found': len(issues),
'issues': issues
}
def check_user_compliance(self, user: Dict) -> List:
"""检查用户合规性"""
issues = []
rules = user['rules']
# 检查是否授予了危险权限
if any('+@admin' in rule for rule in rules):
issues.append(f"用户 {user['username']} 拥有管理员权限")
# 检查Key模式是否过于宽泛
if any('~*' in rule for rule in rules):
issues.append(f"用户 {user['username']} 可以访问所有Key")
return issues

通过这套完整的基于ACL的Redis多租户解决方案,你可以实现:

  • ✅ 严格的数据隔离:每个租户只能访问自己的数据
  • ✅ 细粒度的权限控制:精确到命令级别的权限管理
  • ✅ 资源配额限制:防止单个租户耗尽系统资源
  • ✅ 完整的审计追踪:所有操作都有记录可查
  • ✅ 自动化运维:租户生命周期自动化管理
    这套方案特别适合SaaS平台、云服务提供商等需要为多个客户提供Redis服务的场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/948088.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二分查找边界

二分查找边界二分查找边界Q:给定一个长度为𝑛的有序数组nums ,其中可能包含重复元素。请返回数组中最左一个元素target的索引。若数组中不包含该元素,则返回−1 。查找左边界 回忆二分查找插入点的方法,搜索完成…

求解 LCA 的三种方法及其比较

本文写于 2025 年 10 月 24 日。 昨天看到岁岁似今朝以“学不成名誓不还”的勇气学 LCA(树上最近公共祖先),并感叹“LCA 是我最严厉的母亲”,心血来潮,也学了一下。翻看着洛谷玲琅满目的题解,竟学会了三种方法,…

策略模式优化if-else

class Calculator:def __init__(self):self.strategy = Nonedef set_strategy(self, strategy):self.strategy = strategydef calculate_result(self, num1, num2):return self.strategy.execute(num1, num2)class Add…

捐赠

题目 题目描述 有 \(A\)、\(B\) 两类物品。 paper 打算每类各选 \(k\) 个(\(k\) 可自由决定,可取 \(0\))一起捐出。捐赠的总贡献为所选物品的价值总和。 初始时 paper 没有物品,但是 paper 可以通过一些操作改变物…

学习笔记:重链剖分

本文写于 2025 年 9 月 28 日。 前言 这几天一下课,班里的某位同学就走到我座位旁边,念叨着“来学树剖”。在他的 传销 诈骗 怂恿 鼓励之下,我也终于来到了这座大山面前,但发现似乎也并不难…… 何为重链剖分 考虑…

P3232 [HNOI2013] 游走

考虑贪心。 随机游走则显然每条边期望经过次数越大则其编号应越小。 每条边的期望经过次数难以计数,考虑每个店期望经过次数,设计状态 \(f_i\) 表示点 \(i\) 期望经过次数。 转移: \(f_i=\sum_{v\in e_i}f_v\cdot \…

FRP 后端无法获取请求者IP解决方案

FRP 后端无法获取请求者IP解决方案📝 FRP 后端无法获取请求者真实 IP?别慌,解决方案来啦!🧐 问题背景 当你使用 FRP 进行内网穿透或代理服务时,是否遇到过这样的困扰: 后端服务拿到的客户端 IP 全都是 FRP 服…

正睿 2025 NOIP 20连测 Day9

坐在前面的老哥 AK 了。他怎么这么成功,我怎么这么失败/ll。 T1小 W 有 \(n\) 个球,每个球都有一种颜色,其中第 \(i\) 个球初始的颜色可以用正整数 \(a_i\) 来表示,一共有 \(m\) 种颜色。 在一次染色操作中,小 W …

计算几何初步:CCW 与判断两线段的相交性

本文写于 2025 年 9 月 18 日。 前言 昨天在正睿的“IOI 普及联赛”中,有这样一道题,极大地冲击了本蒟蒻的心灵。赛后查看题解,此题竟然涉及计算几何,这更是本蒟蒻从未涉足的领域。我遂查询资料,学习了 CCW 算法以…

如何选择合适的团队共享网盘?坚果云、亿方云等15款产品横向测评

面对市场上琳琅满目的产品,管理者和技术决策者往往在可靠性、性能、安全性与成本之间难以取舍。本篇文章将围绕企业共享网盘,从功能覆盖、同步效率、安全合规、协作体验等维度,深度评测并对比市面上15款主流产品,帮…

软件工程学习日志2025.10.27

🎯 今日目标 完成基于Trae框架的IT岗位求职记录系统开发,重点训练数据库的增删改查操作能力 💻 项目启动:9:00 AM 技术选型确定 今天开始着手开发老师布置的IT岗位求职记录系统。经过技术调研,我决定采用以下技…

深入解析:TCP/IP 四层模型协作流程详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Windows全版本激活教程(仅供测试)

Windows全版本激活教程(仅供测试)Windows 系统激活指南 注意:本文档及所提供的工具仅供学习、测试和环境验证使用。请确保您遵守软件许可协议,在合法范围内使用。 免责声明 使用任何激活工具都存在潜在风险,包括但不…

基本概念2

1, 访问控制列表步骤一:创建一个访问控制规则 步骤二:调用这个规则基本配置和高级配置 基本配置只能限制源地址,不检查目标地址 高级配置源地址与目标地址都检查步骤一: 命令: acl name test advance # test是给…

20251027周一日记

20251027周一日记前些日: 1.周五玩得挺爽,熬到五点多睡的,转天有点遗憾但还是玩得挺爽。见识到了大城市之间的差距。 2.周六回家,出去吃饭;周日在家,出去吃饭。听家人说各有各在拼搏的方向。 今日: 1.早上睡过了…

【通讯协议】IIC

前言 对于各种协议的知识,假如不常用的话还是很容易忘记和生疏的,于是我会在这篇文章重新学习,顺带记录一下,以便下次复习。由于最近要用到 IIC,所以最先复习 IIC 的内容。 网上有关 IIC 的资料很多也很全面,所以…

Robot Queries

题目传送门 前置知识——向量的加减 \((x_1,y_1) \pm (x_2,y_2) = (x_1\pm x_2,y_1\pm y_2)\)。 满足交换律和结合律。 题目大意 有一个在 \((0,0)\) 的点。现在给出 \(n\) 个操作序列 \({f}\),每个指令形如 \((x, y)…

10月27日

今天上午学了统一建模语言和数构,下午学了Java

特殊的数字签名

盲签名 -- 部分盲签名 -- 群签名盲签名 Chaum盲签名协议 协议流程: \[\begin{flalign} &Setup:\\ &\quad p,q = getPrime(safe.bit\_length);n = p * q;Pubkey = (n, e);Pravitekey = d\\ &Sign:\\ &…

CSP-S 40(爆零记)

10.2710.27 赤到了。 第一次爆蛋。 t1 特判没卡掉11个人。 乐死了。 暴力有80pts。 正解: 发现值域很小只有1000,从此入手。 先预处理 1000 以内的素数,发现很少只有168个,空间可开下,这启发我们对于每个素数记录…