用Spring Boot搭建企业AI安全网关:输入审核、PII脱敏、输出校验与审计
文章摘要
企业接入多个大模型后,若每个业务系统自行处理Moderation、敏感信息脱敏、Prompt Injection、工具权限和日志审计,安全策略很快会失控。本文使用Spring Boot设计一个统一AI安全网关,通过标准请求对象串联身份校验、输入长度限制、PII检测、内容审核、Prompt Injection检测、模型代理、输出DLP和审计日志,并提供可扩展接口与核心代码骨架。
一、网关的目标
统一链路:
业务系统
→ AI安全网关
→ 模型Provider
网关负责:
- 身份与租户;
- 请求配额;
- 模型白名单;
- 输入审核;
- PII检测与脱敏;
- Prompt Injection检测;
- 工具白名单;
- 输出校验;
- 成本与审计;
- 统一错误码。
业务系统负责:
- 业务场景;
- 用户体验;
- 领域权限;
- 最终业务动作。
安全网关不能代替业务权限,但可以提供统一执行点。
二、项目结构
ai-security-gateway
├── controller
│ └── AiGatewayController.java
├── model
│ ├── AiGatewayRequest.java
│ ├── AiGatewayResponse.java
│ └── SecurityDecision.java
├── security
│ ├── SecurityPipeline.java
│ ├── InputLengthGuard.java
│ ├── PiiGuard.java
│ ├── ModerationGuard.java
│ ├── PromptInjectionGuard.java
│ └── OutputGuard.java
├── provider
│ ├── ModelProvider.java
│ └── SpringAiModelProvider.java
├── audit
│ ├── AuditEvent.java
│ └── AuditService.java
└── exception
└── GatewayExceptionHandler.java
三、统一请求对象
public record AiGatewayRequest(
String requestId,
String tenantId,
String userId,
String scenario,
String modelTier,
String message,
Map context,
Set requestedTools
) {
}
注意:
tenantId和userId不应直接信任请求Body,应从认证Token或网关身份上下文写入。
对外请求可以不包含这两个字段,Controller负责补全。
四、统一安全动作
public enum SecurityAction {
ALLOW,
MASK_AND_ALLOW,
SAFE_MODE,
HUMAN_REVIEW,
REJECT
}
public record SecurityDecision(
SecurityAction action,
Set reasons,
String sanitizedText,
Set sensitiveEntities,
double riskScore
) {
public boolean allowed() {
return action == SecurityAction.ALLOW
|| action == SecurityAction.MASK_AND_ALLOW
|| action == SecurityAction.SAFE_MODE;
}
}
五、定义Guard接口
public interface InputGuard {
GuardResult evaluate(
GuardContext context,
String text
);
}
public record GuardResult(
boolean passed,
SecurityAction recommendedAction,
String transformedText,
Set reasons,
double score
) {
}
每个Guard只做一件事,SecurityPipeline负责汇总。
六、输入长度Guard
@Component
public class InputLengthGuard
implements InputGuard {
private static final int MAX_CHARS = 50_000;
@Override
public GuardResult evaluate(
GuardContext context,
String text
) {
if (text == null || text.isBlank()) {
return new GuardResult(
false,
SecurityAction.REJECT,
text,
Set.of("EMPTY_INPUT"),
1.0
);
}
if (text.length() > MAX_CHARS) {
return new GuardResult(
false,
SecurityAction.REJECT,
text,
Set.of("INPUT_TOO_LONG"),
1.0
);
}
return passed(text);
}
}
长度限制应按场景配置,而不是全局固定。
七、PII Guard
实体对象:
public record SensitiveEntity(
String type,
int start,
int end,
String replacement,
String hash
) {
}
基础检测:
@Component
public class PiiGuard implements InputGuard {
private static final Pattern MOBILE =
Pattern.compile("(?");
if (!masked.equals(text)) {
return new GuardResult(
true,
SecurityAction.MASK_AND_ALLOW,
masked,
Set.of("MOBILE_DETECTED"),
0.7
);
}
return passed(text);
}
}
生产环境还应:
- 校验身份证校验位;
- 支持企业自定义字段;
- 保留受控映射;
- 区分允许使用和禁止外发;
- 支持中文姓名与地址NER。
八、Moderation Guard
@Component
public class ModerationGuard
implements InputGuard {
private final ModerationModel moderationModel;
public ModerationGuard(
ModerationModel moderationModel
) {
this.moderationModel = moderationModel;
}
@Override
public GuardResult evaluate(
GuardContext context,
String text
) {
ModerationResponse response =
moderationModel.call(
new ModerationPrompt(text)
);
ModerationSummary summary =
mapResponse(response);
if (summary.highRisk()) {
return new GuardResult(
false,
SecurityAction.REJECT,
text,
summary.categories(),
summary.maxScore()
);
}
return passed(text);
}
}
不要让业务层直接解析Provider特定结构。
九、Prompt Injection Guard
使用规则和模型组合:
@Component
public class PromptInjectionGuard
implements InputGuard {
private final List patterns = List.of(
Pattern.compile("忽略.{0,20}(规则|指令|提示词)"),
Pattern.compile("(输出|打印).{0,20}系统提示词"),
Pattern.compile("(调用|执行).{0,20}(工具|命令)")
);
@Override
public GuardResult evaluate(
GuardContext context,
String text
) {
boolean matched = patterns.stream()
.anyMatch(p -> p.matcher(text).find());
if (matched) {
return new GuardResult(
false,
SecurityAction.HUMAN_REVIEW,
text,
Set.of("PROMPT_INJECTION_SUSPECTED"),
0.75
);
}
return passed(text);
}
}
不能只检测中文固定短语,还需要对抗测试和语义分类。
十、SecurityPipeline
@Service
public class SecurityPipeline {
private final List guards;
public SecurityPipeline(
List guards
) {
this.guards = guards;
}
public SecurityDecision evaluateInput(
GuardContext context,
String originalText
) {
String currentText = originalText;
Set reasons = new LinkedHashSet();
SecurityAction action = SecurityAction.ALLOW;
double maxRisk = 0.0;
for (InputGuard guard : guards) {
GuardResult result = guard.evaluate(
context,
currentText
);
reasons.addAll(result.reasons());
maxRisk = Math.max(maxRisk, result.score());
if (result.transformedText() != null) {
currentText = result.transformedText();
}
action = merge(action, result.recommendedAction());
if (action == SecurityAction.REJECT) {
break;
}
}
return new SecurityDecision(
action,
reasons,
currentText,
Set.of(),
maxRisk
);
}
}
动作优先级:
REJECT
> HUMAN_REVIEW
> SAFE_MODE
> MASK_AND_ALLOW
> ALLOW
十一、模型Provider抽象
public interface ModelProvider {
ModelResult generate(
SafeAiRequest request
);
}
@Service
public class SpringAiModelProvider
implements ModelProvider {
private final ChatClient chatClient;
@Override
public ModelResult generate(
SafeAiRequest request
) {
String content = chatClient.prompt()
.system(request.systemPrompt())
.user(request.sanitizedMessage())
.call()
.content();
return new ModelResult(content);
}
}
Provider层不应绕过安全Pipeline。
十二、模型白名单
public ModelTier resolveModel(
String tenantId,
String scenario,
String requestedTier
) {
ModelPolicy policy = policyRepository.load(
tenantId,
scenario
);
if (!policy.allowedTiers().contains(requestedTier)) {
throw new ModelNotAllowedException();
}
return ModelTier.valueOf(requestedTier);
}
防止业务系统随意使用高成本或未审批模型。
十三、工具白名单
请求中的工具集合必须与服务端策略求交集:
Set allowedTools =
toolPolicyService.allowedTools(
tenantId,
userId,
scenario
);
Set effectiveTools =
requestedTools.stream()
.filter(allowedTools::contains)
.collect(Collectors.toUnmodifiableSet());
不要直接把客户端传来的工具名注册给ChatClient。
十四、输出Guard
输出检查:
PII
Moderation
系统提示词泄露
密钥格式
证据引用
业务禁用表达
接口:
public interface OutputGuard {
GuardResult evaluate(
GuardContext context,
String modelOutput
);
}
高风险输出可以:
- 拒绝;
- 脱敏;
- 重写;
- 转人工;
- 返回安全模板。
不要让同一个模型无条件“自我审核”后直接放行。
十五、Controller完整流程
@PostMapping("/v1/ai/generate")
public AiGatewayResponse generate(
Authentication authentication,
@Valid @RequestBody GatewayInput input
) {
AuthenticatedUser user =
identityService.current(authentication);
AiGatewayRequest request =
requestFactory.create(user, input);
SecurityDecision inputDecision =
securityPipeline.evaluateInput(
GuardContext.from(request),
request.message()
);
auditService.recordInputDecision(
request,
inputDecision
);
if (!inputDecision.allowed()) {
throw new AiSecurityException(
inputDecision.action()
);
}
ModelResult modelResult = modelProvider.generate(
safeRequestFactory.create(
request,
inputDecision
)
);
SecurityDecision outputDecision =
securityPipeline.evaluateOutput(
GuardContext.from(request),
modelResult.content()
);
if (!outputDecision.allowed()) {
throw new AiOutputBlockedException();
}
return responseFactory.create(
request,
outputDecision.sanitizedText()
);
}
十六、审计事件
public record AuditEvent(
String requestId,
String tenantId,
String userIdHash,
String scenario,
String model,
String inputHash,
int inputLength,
SecurityAction inputAction,
SecurityAction outputAction,
Set reasons,
long latencyMs,
Instant createdAt
) {
}
默认不要保存完整输入输出。
敏感原文如需留存,应进入单独加密审计库。
十七、统一错误码
AI_INPUT_BLOCKED
AI_OUTPUT_BLOCKED
AI_HUMAN_REVIEW_REQUIRED
AI_MODEL_NOT_ALLOWED
AI_TOOL_NOT_ALLOWED
AI_SECURITY_SERVICE_UNAVAILABLE
AI_RATE_LIMITED
前端不要看到内部风险规则和阈值。
十八、失败策略
Moderation不可用
高风险场景:
Fail Closed
低风险内部场景:
进入SAFE_MODE
DLP不可用
含敏感数据的业务应拒绝或转人工。
审计服务不可用
高风险工具调用应阻断;普通问答可以写入本地可靠队列后继续。
十九、可观测性
指标:
ai_gateway_requests_total
ai_gateway_blocked_total
ai_gateway_review_total
ai_gateway_pii_detected_total
ai_gateway_injection_detected_total
ai_gateway_security_latency
ai_gateway_model_latency
ai_gateway_output_blocked_total
标签不要使用原始userId或Prompt,避免高基数和隐私泄露。
二十、生产补齐项
- Redis配额;
- OPA或Cedar策略引擎;
- OpenTelemetry;
- 密钥管理;
- 模型路由;
- 流式输出安全;
- 文件上传沙箱;
- 多模态审核;
- 人工审核后台;
- 对抗测试集;
- 灰度规则发布。
总结
企业AI安全网关的核心价值是把分散在各业务系统中的控制统一为:
身份
→ 输入安全
→ 数据脱敏
→ 模型与工具策略
→ 输出安全
→ 审计
它不替代业务权限,但可以成为所有模型调用必须经过的统一安全执行点。
延伸阅读
如果你正在关注Spring Boot、企业AI安全、RAG、Agent与模型网关建设,欢迎访问 智元界:
https://www.zyentor.com/
智元界将持续分享可运行的技术实战、架构设计、问题排查与企业应用案例。