安全
大约 4 分钟
第九章:安全与合规治理
9.1 先明确:AI 应用的“风险面”在哪里
传统 Web 应用的主要风险在:鉴权、注入、越权、数据泄露。
AI 应用在这些基础上,会新增或放大三类风险:
- Prompt 注入:用户诱导模型忽略规则、泄露机密、调用高危工具
- 越权工具调用:模型建议执行“查询他人订单/退款/删数据”等动作
- 输出合规:输出带敏感信息、泄露密钥、泄露内部文档
这一章给一套“最小安全基线”,你可以直接落地到项目里。
9.2 密钥管理:不要把 API Key 写进仓库
推荐做法:
- 本地开发:环境变量
- 线上:密钥管理服务(KMS/Secrets Manager)或配置中心加密
示例(环境变量注入):
spring:
ai:
dashscope:
api-key: ${AI_DASHSCOPE_API_KEY:}9.3 Prompt 注入防护:把“规则”做成系统层 + 工具层
一条经验非常重要:
system 规则只能降低风险,不能替代工具侧的权限与校验。
你应该做到两层防护:
- Prompt 规则层:告诉模型哪些事情绝对不能做
- 执行层:工具白名单、参数校验、鉴权、审计、超时限流
示例 system(规则层):
你是企业助手:
1) 不要泄露任何密钥、Token、内部链接与用户隐私。
2) 工具调用只允许使用已注册工具;不得臆造函数。
3) 任何涉及查询用户数据与执行动作,必须遵循权限与审计要求。9.4 输出脱敏:防止日志与响应泄露敏感信息
建议把“脱敏”做成一个可复用组件,并且在日志里永远记录脱敏后的文本。
9.4.1 脱敏组件
package com.example.saa.security;
import java.util.Objects;
import java.util.regex.Pattern;
import org.springframework.stereotype.Component;
@Component
public class SensitiveDataRedactor {
private static final Pattern PHONE = Pattern.compile("(\\b1\\d{2})\\d{4}(\\d{4}\\b)");
private static final Pattern API_KEY_LIKE = Pattern.compile("(?i)(api[-_ ]?key|token)\\s*[:=]\\s*([A-Za-z0-9_\\-]{10,})");
public String redact(String input) {
String text = Objects.toString(input, "");
text = PHONE.matcher(text).replaceAll("$1****$2");
text = API_KEY_LIKE.matcher(text).replaceAll("$1=***");
return text;
}
}9.4.2 单元测试示例(边界:空输入、手机号、Key)
package com.example.saa.security;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
public class SensitiveDataRedactorTest {
@Test
void should_redactPhone_when_containsPhone() {
SensitiveDataRedactor redactor = new SensitiveDataRedactor();
assertEquals("联系我:138****5678", redactor.redact("联系我:13812345678"));
}
@Test
void should_redactApiKey_when_containsApiKeyLike() {
SensitiveDataRedactor redactor = new SensitiveDataRedactor();
assertEquals("apiKey=***", redactor.redact("apiKey=sk-1234567890abcdef"));
}
}9.5 工具调用的安全边界:白名单 + 参数校验 + 鉴权 + 审计
把工具调用当成“高危入口”来设计,你至少要做到:
- 白名单:只注册固定工具集合
- 参数校验:格式、长度、枚举、范围
- 鉴权:执行工具前,按用户身份检查权限
- 审计:记录调用元信息(requestId、userId、toolName、耗时、结果状态)
一个常用的工程化写法是:工具方法接收 arguments,但鉴权信息来自“请求上下文”,而不是让模型传入。
package com.example.saa.security;
import org.springframework.stereotype.Service;
@Service
public class AuthorizationService {
public void requireRole(String role, String required) {
if (role == null || !role.equalsIgnoreCase(required)) {
throw new SecurityException("权限不足,需要角色: " + required);
}
}
}9.6 本章小结
你已经拿到一套可落地的最小安全基线:
- 密钥不入库:环境变量/密钥服务
- Prompt 规则层 + 工具执行层双重防护
- 输出脱敏:日志与响应都要过一遍
- 工具调用必须:白名单、校验、鉴权、审计、超时限流
下一章我们会把“线上可治理”补齐:错误分层、超时重试、可观测性(日志/指标/追踪)与告警。 点击这里👇🏻获取:100万QPS短链系统、复杂的商城微服务系统、智能翻译助手AI Agent、SaaS点餐系统、刷题吧小程序、商城系统、秒杀系统、AI项目、代码生成神器、苏三demo项目、智能天气播报AI Agent、智能代码审查AI Agent等 10 个项目的:项目源代码、开发教程和技术答疑
