
1. 引言1.1 安全挑战AI 智能体系统面临独特的安全挑战:凭证泄露风险:API Key、数据库密码等敏感信息可能被恶意技能窃取技能注入攻击:第三方技能可能执行恶意代码数据泄露:用户对话历史、个人隐私可能通过技能外泄权限提升:低权限技能可能通过漏洞获取高权限重放攻击:攻击者截获请求后重复发送1.2 安全设计原则OpenClaw 的安全架构遵循以下原则:零信任:不信任任何外部技能,默认隔离最小权限:技能只拥有完成功能所需的最小权限纵深防御:多层安全措施,单点失效不影响整体审计可追溯:所有操作都有日志记录2. Token + Nonce 认证机制2.1 认证流程┌─────────┐ ┌─────────┐ ┌─────────┐ │ Client │ │ Server │ │ Redis │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ │ 1. 请求 Nonce │ │ │─────────────────────────────│ │ │ │ 2. 生成并存储 Nonce │ │ │─────────────────────────────│ │ │ │ │ 3. 返回 Nonce │ │ │─────────────────────────────│ │ │ │ │ │ 4. 请求 API (含 Token+Nonce)│ │ │─────────────────────────────│ │ │ │ 5. 验证 Nonce │ │ │─────────────────────────────│ │ │ │ │ │ 6. 返回验证结果 │ │ │─────────────────────────────│ │ │ │ │ │ 7. 验证 Token │ │ │ │ │ │ 8. 执行请求 │ │ │ │ │ 9. 返回结果 │ │ │─────────────────────────────│ │ │ │ │2.2 Nonce 生成与验证importsecretsimporthashlibimporttimefromtypingimportOptionalfromdataclassesimportdataclass@dataclassclassNonceEntry:"""Nonce 条目"""nonce:strcreated_at:floatexpires_at:floatused:bool=FalseclassNonceManager:"""Nonce 管理器"""def__init__(self,redis_client,ttl:int=300):""" 初始化 Args: redis_client: Redis 客户端 ttl: Nonce 有效期(秒),默认 5 分钟 """self.redis=redis_client self.ttl=ttl self.key_prefix="openclaw:nonce:"defgenerate(self,client_id:str)-str:""" 生成 Nonce Args: client_id: 客户端 ID Returns: str: 生成的 Nonce """# 生成加密安全的随机数nonce=secrets.token_urlsafe(32)# 创建 Nonce 条目entry=NonceEntry(nonce=nonce,created_at=time.time(),expires_at=time.time()+self.ttl)# 存储到 Rediskey=f"{self.key_prefix}{client_id}:{nonce}"self.redis.setex(key,self.ttl,self._serialize_entry(entry))returnnoncedefverify(self,client_id:str,nonce:str)-bool:""" 验证 Nonce Args: client_id: 客户端 ID nonce: 待验证的 Nonce Returns: bool: 验证是否通过 """key=f"{self.key_prefix}{client_id}:{nonce}"# 从 Redis 获取entry_data=self.redis.get(key)ifnotentry_data:returnFalseentry=self._deserialize_entry(entry_data)# 检查是否已使用ifentry.used:# 防止重放攻击:已使用的 Nonce 无效returnFalse# 检查是否过期iftime.time()entry.expires_at:# 删除过期的 Nonceself.redis.delete(key)returnFalse# 标记为已使用entry.used=Trueself.redis.setex(key,self.ttl,self._serialize_entry(entry))returnTruedef_serialize_entry(self,entry:NonceEntry)-str:"""序列化条目"""returnf"{entry.nonce}:{entry.created_at}:{entry.expires_at}:{entry.used}"def_deserialize_entry(self,data:str)-NonceEntry:"""反序列化条目"""parts=data.split(':')returnNonceEntry(nonce=parts[0],created_at=float(parts[1]),expires_at=float(parts[2]),used=parts[3].lower()=='true')2.3 Token 验证importjwtimporthmacfromfunctoolsimportwrapsclassTokenValidator:"""Token 验证器"""def__init__(self,secret_key:str,algorithm:str="HS256"):self.secret_key=secret_key self.algorithm=algorithmdefvalidate(self,token:str)-Optional[dict]:""" 验证 Token Args: token: JWT Token Returns: dict: Token Payload,验证失败返回 None """try:# 验证并解码payload=jwt.decode(token,self.secret_key,algorithms=[self.algorithm],options={"verify_exp":True,# 验证过期时间"verify_iat":True,# 验证签发时间"require":["exp","iat","sub"]# 必填字段})returnpayloadexceptjwt.ExpiredSignatureError:# Token 已过期returnNoneexceptjwt.InvalidTokenErrorase:# 其他 Token 错误print(f"Token validation failed:{e}")returnNonedefgenerate_token(self,client_id:str,scopes:list,expires_in:int=86400)-str:""" 生成 Token Args: client_id: 客户端 ID scopes: 权限范围 expires_in: 有效期(秒),默认 24 小时 Returns: str: 生成的 Token """now=int(time.time())payload={"sub":client_id,"iat":now,"exp":now+expires_in,"scopes":scopes,"jti":secrets.token_urlsafe(16)# 唯一 ID,防止重放}token=jwt.encode(payload,self.secret_key,algorithm=self.algorithm)returntoken2.4 认证中间件fromflaskimportrequest,jsonify,gfromfunctoolsimportwrapsclassAuthMiddleware:"""认证中间件"""def__init__(self,token_validator