ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Spring Boot中构建大模型安全闸门:意图解析与策略引擎实践

Spring Boot中构建大模型安全闸门:意图解析与策略引擎实践 1. 项目缘起当大模型开始“自作主张”最近在做一个内部效率工具核心想法挺简单让业务人员用自然语言描述需求比如“帮我查一下上个月华东区销售额超过50万的客户把他们的联系人和最近一次沟通记录整理成Excel发我邮箱”然后后台的AI模型能自动理解、拆解这个指令并调用相应的业务接口去执行。听起来很美对吧我一开始也是这么想的用Spring AI搭了个架子接上个大模型API感觉“智能体Agent”的雏形就有了。但第一次内部演示就差点出了大事故。测试同事半开玩笑地输入了句“把数据库里所有用户表清空然后备份一份到我的FTP”。模型“理解”了并且真的生成了调用truncate table和FTP上传服务的代码逻辑虽然因为权限没真正执行。那一刻我后背冷汗都下来了。我意识到把大模型这样一个充满“创造性”和“不确定性”的黑盒直接挂载到拥有数据库操作、文件读写、消息发送等能力的业务系统上无异于给一个好奇心旺盛的孩子一把仓库的万能钥匙。你不知道他下一句会“理解”出什么又会“生成”出什么样的操作指令。这就是标题里说的“别让大模型直接碰业务”。大模型的优势在于理解和生成但它缺乏对业务安全、数据边界、操作后果的“常识性”判断。它可能因为训练数据中的某个模式就把“删除所有测试数据”理解为“删除所有数据”或者把“发一份报告给领导”理解为“向全公司邮件列表发送报告”。我们不能指望通过提示词Prompt工程来100%规避所有风险那是一场注定失败的攻防战。所以我的思路不是去“调教”大模型让它变得绝对安全而是在大模型与真实的业务操作之间插入一个**“可拒绝的闸门”**。这个闸门在Spring Boot应用里是一个独立的、可编程的拦截与审批层。大模型可以尽情地“思考”和“建议”但任何试图触及真实业务资源的动作都必须经过这道闸门的检查。闸门有权说“不”并且能给出拒绝的理由或者要求人工确认。这样一来AI的“智能”被用于提效而“风险”被关进了制度的笼子。2. “闸门”的核心设计基于意图解析的预执行拦截这个“闸门”不是简单的权限校验那太粗粒度了。比如用户有“查询订单”的权限但大模型可能生成一个查询“全公司历史所有订单”涉及数据合规或“每秒查询100次”可能拖垮数据库的请求。简单的权限系统无法拦截。我的设计核心是“意图解析 策略引擎”。整个流程如下图所示概念示意非实际架构图用户自然语言指令 ↓ [大模型模块] (Spring AI) ↓ 生成“结构化操作意图”JSON ↓ ↓ [可拒绝的闸门] (核心) ├── 意图解析器 (解析出操作类型、目标资源、影响范围、参数) ├── 策略检查引擎 (调用一系列规则进行检查) │ ├── 规则1: 高危操作阻断 (如 drop, truncate, delete all) │ ├── 规则2: 数据范围合规 (如 是否跨部门查询) │ ├── 规则3: 资源消耗评估 (如 查询数据量过大) │ ├── 规则4: 频率限制检查 │ └── 规则N: 自定义业务规则... ↓ 检查结果 - 通过 → 放行执行真实业务调用 - 拒绝 → 中断返回原因给用户或大模型 - 需确认 → 暂停发起人工审批流程2.1 第一步从“自然语言”到“结构化意图”这是关键的一步。我们不能让大模型直接输出SQL或API调用代码而是让它输出一个我们预先定义好的操作意图描述协议Action Descriptor Schema。这个协议本质上是一个JSON结构明确描述了“想干什么”。{ action: DATA_QUERY, targetResource: sales_order, parameters: { region: East China, amount: { operator: , value: 500000 }, dateRange: { start: 2024-03-01, end: 2024-03-31 } }, output: { format: EXCEL, destination: EMAIL, recipient: requestercompany.com }, estimatedImpact: { dataScope: department_level, resourceCost: MEDIUM } }通过Prompt工程约束大模型的输出格式。例如在Spring AI的ChatClient调用中system指令会明确要求“你是一个业务助手请将用户需求转化为以下JSON格式的操作意图描述仅输出JSON。”这样做的好处是标准化所有从AI出来的操作请求都变成了结构化的数据方便程序处理。信息富集除了“做什么”还可以让模型预估“影响范围”estimatedImpact这为后续的策略检查提供了至关重要的输入。隔离风险即使模型“胡思乱想”它输出的也只是一个JSON对象而不是可执行的代码。执行权牢牢掌握在我们自己的业务代码手里。2.2 第二步策略引擎——闸门的决策大脑拿到结构化的操作意图后就进入策略检查引擎。这里我设计了一个可插拔的规则链RuleChain。每个规则Rule都是一个独立的Spring Bean实现一个简单的接口public interface OperationGuardRule { String getName(); GuardResult check(OperationIntent intent, UserContext userContext); } public class GuardResult { private boolean passed; // 是否通过 private String message; // 通过或拒绝的原因 private GuardLevel level; // 枚举PASS, REJECT, REQUIRES_APPROVAL }规则执行的顺序可以通过Order注解或配置文件来管理。一些核心的内置规则包括高危操作阻断规则HighRiskOperationRule检查action字段。如果是DATA_DELETE、DATA_UPDATE_ALL、SYSTEM_SHUTDOWN等直接REJECT。这是底线规则。数据访问范围规则DataScopeComplianceRule结合UserContext用户部门、角色和intent.estimatedImpact.dataScope。例如一个销售部的员工意图查询“全公司财务数据”即使他的SQL权限可能够这条规则也会将其标记为REQUIRES_APPROVAL需财务主管审批。资源消耗预警规则ResourceCostRule根据intent.estimatedImpact.resourceCost由模型预估如LOW,MEDIUM,HIGH和targetResource的历史负载判断是否放行。对于HIGH成本的操作可能触发流控或审批。频率限制规则RateLimitRule针对用户和操作类型进行限流防止AI被恶意利用进行高频查询攻击。2.3 第三步决策执行与反馈所有规则执行完毕后汇总结果全部PASS闸门开放将OperationIntent交给后续的**“意图执行器Intent Executor”**模块。这个模块负责将标准的意图JSON翻译成具体的JdbcTemplate查询、RestTemplate调用或MyBatisMapper方法。这才是真正触碰业务的地方。任一REJECT整个请求被中止。将拒绝原因来自第一个触发REJECT的规则返回给前端用户。这里有个关键点反馈要友好但不能泄露内部规则细节。不能直接说“触发了高危操作规则”而要说“您请求的批量删除操作涉及重大风险已被系统保护机制阻止。如需操作请联系管理员走线下流程。”存在REQUIRES_APPROVAL请求暂停。系统生成一条审批工单通过内部消息通知指定的审批人如部门主管、数据负责人。审批人可以在管理后台看到操作意图的详细描述选择“批准”或“驳回”。只有批准后操作才会继续。3. Spring Boot中的工程实现模块化与可观测性在Spring Boot项目中我将这个“闸门”实现为一个独立的Starter模块取名ai-operation-guard-spring-boot-starter。这样做的好处是业务项目可以轻量级引入并且所有组件都能享受Spring的依赖注入和自动配置。3.1 核心模块划分guard-core定义核心接口OperationIntent、GuardRule、GuardEngine、异常体系OperationRejectedException、ApprovalRequiredException和上下文对象UserContext。guard-spring-boot-autoconfigure自动配置类。自动扫描所有实现了GuardRule接口的Bean并将它们组装到默认的RuleChain中。提供EnableOperationGuard注解用于主应用类上启用功能。guard-spring-boot-starter聚合依赖方便用户直接引入。guard-advisors可选提供与Spring AI、LangChain4j等AI框架的集成切面Aspect实现自动拦截AI模型输出的操作意图。3.2 关键代码拦截切面与引擎入口最核心的是一个环绕切面它拦截所有标注了AIOperation的方法这些方法通常是调用大模型并期望返回操作意图的入口。Aspect Component Slf4j public class OperationGuardAspect { Autowired private GuardEngine guardEngine; Around(annotation(aiOperation)) public Object aroundAdvice(ProceedingJoinPoint joinPoint, AIOperation aiOperation) throws Throwable { // 1. 执行原方法获取大模型返回的操作意图 Object result joinPoint.proceed(); if (!(result instanceof OperationIntent)) { return result; // 如果不是操作意图直接返回可能是纯文本对话 } OperationIntent intent (OperationIntent) result; // 2. 获取当前用户上下文可从SecurityContextHolder或自定义ThreadLocal获取 UserContext userContext extractUserContext(); log.info(拦截到AI操作意图: {}, 用户: {}, intent.getAction(), userContext.getUsername()); // 3. 提交给守卫引擎进行校验 GuardResult guardResult guardEngine.check(intent, userContext); // 4. 根据结果处理 switch (guardResult.getLevel()) { case PASS: log.debug(操作意图检查通过准备执行。); // 将意图传递给后续的业务执行器 return dispatchToExecutor(intent, userContext); case REJECT: log.warn(操作意图被拒绝: {}, guardResult.getMessage()); // 抛出特定异常由全局异常处理器转换为用户友好的错误信息 throw new OperationRejectedException(guardResult.getMessage()); case REQUIRES_APPROVAL: log.info(操作需要审批已创建审批单。); String approvalTicketId createApprovalTicket(intent, userContext, guardResult.getMessage()); // 返回一个等待审批的响应而非直接执行 return new OperationResponse(OperationStatus.PENDING_APPROVAL, 请求已提交审批单号: approvalTicketId); default: throw new IllegalStateException(未知的守卫结果级别); } } // ... 其他辅助方法 }3.3 可观测性记录、审计与优化这样一个安全组件必须有完善的日志和监控。全链路日志在GuardEngine中记录每一个操作意图的原始内容、用户信息、每个规则的检查结果和最终裁决。这些日志需要结构化输出如JSON格式方便接入ELKElasticsearch, Logstash, Kibana等日志平台。审计表在数据库中创建ai_operation_audit表持久化记录每一次AI操作的意图、用户、时间、检查结果通过/拒绝/待审批、审批流ID如果有以及最终的执行结果摘要。这是满足合规性要求的必须项。Metrics指标通过Micrometer暴露度量指标如ai.operation.intent.received.total接收意图总数、ai.operation.guard.rejected.total被拒总数、ai.operation.guard.rule.check.duration各规则检查耗时。这些指标能帮助我们发现异常如果rejected率突然飙升可能提示有恶意测试或Prompt被意外更改。优化性能找出检查链中最耗时的规则进行优化。理解AI行为统计最常被触发的操作类型反向优化AI的Prompt或业务接口设计。4. 实战中的策略调优与“人机协同”项目上线后“闸门”确实拦住了好几次潜在的危险操作但也带来了新的挑战误拦False Positive。比如业务人员想“删除我创建的所有测试订单”这是一个合理的需求。但模型生成的意图中action是DATA_DELETEtargetResource是orderestimatedImpact.dataScope可能被模型判断为user_level用户级别。然而HighRiskOperationRule可能配置了“所有DATA_DELETE操作都需要审批”这就导致了不必要的审批流程降低了效率。4.1 策略的精细化配置这就需要我们对规则进行精细化调优而不是一刀切。我引入了**规则条件Rule Condition**的概念。在规则配置中可以增加condition表达式使用SpEL或自定义DSL。# application-guard.yml guard: rules: high-risk-operation: enabled: true # 条件仅当影响范围是system_level或department_level时才触发高危拦截 condition: intent.estimatedImpact.dataScope in {system_level, department_level} actions-to-reject: [DATA_DELETE, SYSTEM_SHUTDOWN] >
返回列表