news 2026/10/20 15:13:49

Apache Shiro反序列化漏洞:流量特征分析与检测防御实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Apache Shiro反序列化漏洞:流量特征分析与检测防御实战

最近处理了一起涉及Shiro框架的告警,流量侧的表现非常典型:攻击者对着某个业务系统反复发送携带异常rememberMe Cookie的请求,Cookie值长度离谱,且Base64解码后能看到明显的Java序列化魔法头。这类针对Apache Shiro反序列化漏洞(CVE-2016-4437)的探测和利用,在真实攻防中依然高频出现。这篇就完整拆解一下这个漏洞的流量特征,以及我实际用过的检测和防御思路。


1. 漏洞原理回顾:RememberMe功能与反序列化链路

1.1 RememberMe的运行机制

Shiro是Java生态里非常主流的权限框架,认证、授权、会话管理都用它。其中“RememberMe”是登录后“记住我”的功能:用户勾选记住登录状态,服务端把用户身份信息写入Cookie,后续请求带上这个Cookie就能恢复登录态,不用反复输入账号密码。

这个过程不是简单存个用户名,Shiro的处理方式是:

  1. 登录成功后,把用户主体对象(Principal)序列化。
  2. 用AES密钥对序列化后的字节数组做加密。
  3. 将密文进行Base64编码。
  4. 写入Cookie,字段名为rememberMe。

请求再次进来时,服务端反着来一遍:读取rememberMe Cookie值,Base64解码,AES解密,然后做Java反序列化,还原用户主体对象,完成会话恢复。

问题就出在最后一步“反序列化”上。Java反序列化本身就是一个高风险操作,如果反序列化的数据是攻击者可控的,攻击者就能在目标系统上执行任意命令。而Shiro恰恰把攻击者的输入直接送进了反序列化流程,等于把一把上了膛的枪交到了路人手里。

1.2 默认密钥为何是罪魁祸首

Shiro的AES加密需要密钥,而老版本Shiro在配置里写死了一个默认密钥,Base64编码后是固定的字符串。也就是说,全世界所有使用默认配置的Shiro系统,加解密用的都是同一把钥匙。

攻击者只要拿到这个默认密钥,就能自己伪造任意rememberMe Cookie:

  • 构造一个恶意Java序列化对象(比如完整的命令执行链)。
  • 用默认密钥对它做AES加密。
  • Base64编码后塞进Cookie发给目标。
  • 目标服务端用同一把默认密钥解密,再反序列化,攻击代码落地执行。

这就好比小区所有住户都用同一个锁芯的钥匙,攻击者手里已经有这把钥匙了,剩下的只是挨家挨户试一下哪家门锁没换过。

1.3 从认证到RCE的完整链路

整个攻击链路可以概括为五个环节:

  1. 攻击者获取默认AES密钥。
  2. 构造恶意反序列化Payload,使用已知密钥进行AES加密与Base64编码。
  3. 将构造结果作为rememberMe Cookie值发送至目标站点任意路径(无需真实登录)。
  4. Shiro对Cookie执行Base64解码与AES解密,将解密后的字节流交给ObjectInputStream进行反序列化。
  5. 反序列化过程中触发恶意类构造器或方法,完成远程命令执行。

理解这条链路对做防御非常重要。很多人只知道“Shiro出过漏洞”,但说不清楚流量层面应该看什么。实际上从这条链路的每一步都能提取出检测特征:Cookie长度、Cookie内容、请求行为、响应差异,四个方面各有信号,下面逐一展开。


2. 攻击视角下的流量特征全景

2.1 Cookie长度与基数的异常信号

先从最容易量化的特征说起:长度。

正常业务场景下,rememberMe Cookie保存的是用户主体对象的序列化结果。普通用户对象的序列化数据通常只包含用户ID、用户名、角色标识、过期时间等少量字段,经过AES加密和Base64编码后,长度一般在几百个字符以内。

我统计过几个生产环境的正常样本:轻量用户对象产生的rememberMe值大约在200到500字符之间。如果用户对象里塞了菜单列表、权限集合这类额外信息,也只有几百字符,极少超过1000字符。

攻击Payload则完全不同。常用的命令执行利用链(比如基于CommonsCollections组件构造的链)序列化后体积很大,Base64编码后通常在2000字符以上,动辄超过5000字符。原因很简单:利用链要构造复杂的对象嵌套关系和反射调用逻辑,字节码天然膨胀。

所以第一个检测信号就是Cookie长度:rememberMe值长度超过1000字符就值得警惕,超过2000字符基本可以判定为恶意探测或攻击载荷。

这里有一个需要说明的点:如果系统本身在用户对象里保存了非常多自定义业务数据,正常Cookie也可能很长,这种情况下不能单靠长度一刀切,需要结合其他特征做综合判断。但绝大多数业务系统的正常Cookie长度是稳定的,设定阈值后先做粗筛,再对命中样本做内容分析,是实际效果最好的做法。

2.2 内容特征:Base64解码后的序列化痕迹

长度异常的Cookie是“形”,内容特征则是“神”。

Java序列化数据有一个固定的文件头,十六进制是AC ED 00 05,对应Java序列化流协议版本标识。这个特征极其稳定,所有标准Java序列化对象都以这段字节开头。

因为rememberMe是Base64编码传输,所以流量特征分析时必须先对Cookie值做Base64解码,再去看解码后的字节流,操作顺序不能反。解码后如果看到AC ED 00 05开头的字节序列,说明这是一个Java序列化对象。

当然,正常的rememberMe Cookie解码后也是Java序列化对象,也会以AC ED 00 05开头。所以这个特征的真正价值在于:先过滤出所有Java序列化对象流量,再结合其他特征缩小范围。

更关键的内容特征是Cookie中携带的Payload特征。主流的反序列化利用工具在生成Payload时,序列化数据中会包含命令执行相关的类名、方法名、命令行字符串。比如命令内容会以明文形式存在于序列化数据中,因此Base64解码后的字节流里可以匹配到常见命令字符串(如/bin/sh、bash、cmd.exe、whoami等)。

在实际检测中这是一个高效信号:超长Cookie + 解码后含命令执行特征字符串,基本可以锁定攻击。

注意,目前利用工具生成的Payload中,命令字符串可能有编码和混淆变体,但大量批量扫描和自动化攻击仍然沿用默认参数,这类特征在真实流量中的召回率相当可观。

2.3 行为特征:密钥探测与利用阶段的请求模式

单个请求的特征是“点”,攻击者的行为模式是“面”,结合起来才能避免单点误判。

CVE-2016-4437利用的前提是确认目标服务端使用了默认密钥。攻击者通常会先做密钥探测:构造几个不同的Payload(或者直接用已知默认密钥加密的探测对象),发送到目标站点,观察响应差异来判断密钥是否正确。

行为特征上有几个高频模式:

  • 同一源IP在短时间内对同一URL路径发送大量请求,每次请求的rememberMe Cookie值都不同。
  • 每个Cookie值都是随机的长字符串,且长度明显超出正常范围。
  • 请求往往不需要完整登录态,直接携带Cookie访问任意URL,甚至静态资源路径。
  • 攻击者会使用同一个Cookie值对多个路径发起探测,寻找存在反序列化漏洞的入口。
  • 密钥测试阶段会发送几个到几十个探测请求,确认密钥正确后会立即发送真正的大体积攻击Payload。

这种“批量探测+重点打击”的行为节奏,和正常用户访问完全不同。正常用户不会在几秒内对同一路径发送十几个不同内容的Cookie请求,更不会每次都携带一个完全不同的超长记住我Cookie。

在日志分析和流量审计中,以源IP+时间窗口+Cookie变化频率作为维度做聚合统计,很容易把这部分攻击行为从背景流量里剥离出来。

2.4 响应特征:服务端可用性的指示信号

响应侧同样有信号。

Shiro在处理rememberMe Cookie时有一个标准流程:如果AES解密失败(密钥错误、数据被篡改、格式不正确),会抛出异常,并在响应中设置一个特殊的Cookie:rememberMe=deleteMe。

攻击者的密钥探测本质就是利用这个行为差异:

  • 发送构造的恶意Cookie,如果服务端解密失败,响应头会出现rememberMe=deleteMe。
  • 如果密钥碰对了,解密成功,服务端会进入反序列化流程,响应头中反而不一定出现deleteMe,同时可能伴随异常响应、响应时间异常或特定回显内容。

因此,从防御视角观察响应特征,有几类情况值得关注:

  • 响应头包含rememberMe=deleteMe,且请求的Cookie值是一个超长随机串,这通常是密钥探测失败的特征。
  • 请求Cookie值异常,但响应头没有deleteMe标记,说明服务端可能成功解密了攻击流量,这是更危险的信号,需立即排查是否已经发生命令执行。
  • 响应中包含非业务逻辑产生的回显内容,比如命令执行结果。

响应特征要和请求特征配合使用,单看响应会漏掉大量侦察阶段的行为,单看请求又容易误伤正常业务。


3. 流量检测落地:日志分析与规则编写

3.1 检测维度与特征工程

把上面四个维度的信号落到工程层面,推荐按以下步骤组织检测逻辑。

先明确数据源。优先级从高到低:

  • 网络层流量抓包(全流量镜像)覆盖最全,能抓到加密链路解密前的完整HTTP报文。
  • Web服务器访问日志(Nginx/Apache)能记录URL、Cookie、状态码、响应头,但通常不记录响应头细节。
  • 安全设备日志(WAF/IDS)通常已经做了一轮规则过滤,需要看命中明细。
  • 应用日志(Shiro框架日志)能直接看到反序列化异常堆栈,是最准确的信号源。

我实际做检测时,最常用的组合是“访问日志粗筛+全流量精细分析”:先用访问日志快速定位可疑请求和源IP,再去全流量里提取完整会话,确认攻击是否成功。

特征工程的核心维度:

维度字段判别逻辑
Cookie长度rememberMe值字符数超过1000告警,超过2000高危
内容特征Base64解码后字节流匹配AC ED 00 05、命令执行特征
请求行为源IP+时间窗口+Cookie变化次数同一IP短时间大量不同超长Cookie
请求路径任意路径携带异常Cookie正常业务不会对静态资源发这种请求
响应标记Set-Cookie中deleteMe出现频率高频deleteMe伴随超长Cookie为探测行为
利用链特征解码后匹配常见利用链类名和方法名如CommonsCollections相关特征串

3.2 WAF/IDS规则的实战写法

基于上述维度,可以把检测规则拆成两类:单包规则和会话规则。

单包规则适合部署在WAF或IDS上,对每个请求独立判断。一种可行的配置思路:

  • 第一步,提取Cookie中的rememberMe参数值。
  • 第二步,检查长度阈值。
  • 第三步,对超长值做Base64解码(注意容错处理,解码失败也告警)。
  • 第四步,在解码后的数据中匹配序列化头部特征和命令执行特征。

关键点:规则中一定要做Base64解码后再匹配,直接对Cookie原文匹配会漏掉大量Payload,因为Java序列化的特征字节经过Base64编码后已经变成了完全不同的ASCII字符序列。

Base64解码的正则表达式写法要宽松,不同攻击工具生成的Payload在Base64编码时可能包含换行符、空格等空白字符,解码前需要做清洗。

以一个简单的Web网关内置规则引擎为例,检测逻辑可以这样描述:

1. 从Cookie中取rememberMe字段 2. 清除字符串中的空白字符 3. 尝试Base64解码 4. 解码失败且长度超阈值 -> 可疑 5. 解码成功且头4字节等于 AC ED 00 05 -> 标记为Java序列化对象 6. 标记为Java序列化对象且长度超阈值 -> 高危告警 7. 在解码内容中匹配命令执行特征字符串 -> 严重告警

会话规则适合部署在日志分析平台。以时间窗口、源IP、目标IP+端口为聚合键,统计异常Cookie请求次数。当同一源IP在5分钟内发送超过20个不同rememberMe长值时,判定为密钥爆破行为。

3.3 日志分析脚本的思路

如果手头只有访问日志,没有全流量镜像,也可以做一些基础但有效的离线分析。思路是解析日志中的Cookie字段,还原rememberMe值,做长度统计和特征匹配。

Python脚本可以做这样几件事:从日志行中正则提取rememberMe字段、计算长度、分布统计、筛选超长样本、对超长样本做Base64解码并匹配特征。下面是核心思路的代码骨架:

import base64 import re # 日志格式示例:Nginx combined格式 # 需要根据实际日志格式调整正则 LOG_PATTERN = re.compile( r'(?P<remote_addr>[\d\.]+).*?"(?P<request>GET|POST)[^"]*?" ' r'(?P<status>\d+) ' ) COOKIE_PATTERN = re.compile(r'(?:^|;)\s*rememberMe=(?P<value>[^;]+)') JAVA_SERIAL_MAGIC = b'\xac\xed\x00\x05' SUSPICIOUS_STRINGS = [ 'bash', '/bin/sh', 'cmd.exe', 'whoami', 'Runtime', 'ProcessBuilder' ] THRESHOLD_LENGTH = 1000 def analyze_log_line(line): match = LOG_PATTERN.search(line) if not match: return None cookie_m = COOKIE_PATTERN.search(line) if not cookie_m: return None raw_value = cookie_m.group('value').strip() if len(raw_value) < THRESHOLD_LENGTH: return None try: cleaned = re.sub(r'\s+', '', raw_value) # 补齐Base64填充 padded = cleaned + '=' * (-len(cleaned) % 4) decoded = base64.b64decode(padded, validate=False) except Exception: return {'source': match.group('remote_addr'), 'status': match.group('status'), 'length': len(raw_value), 'decoded_length': -1, 'serial_head': False, 'hits': [], 'raw_sample': raw_value[:80]} hits = [s for s in SUSPICIOUS_STRINGS if s.encode('utf-8', errors='ignore') in decoded] return { 'source': match.group('remote_addr'), 'status': match.group('status'), 'length': len(raw_value), 'decoded_length': len(decoded), 'serial_head': decoded[:4] == JAVA_SERIAL_MAGIC, 'hits': hits, 'raw_sample': raw_value[:80], } # 示例:逐行处理日志 def scan_log_file(log_path): alerts = [] with open(log_path, 'r', encoding='utf-8', errors='ignore') as f: for line in f: result = analyze_log_line(line) if result and (result['serial_head'] or result['hits']): alerts.append(result) return alerts

实际使用时需要根据日志字段顺序调整正则,核心逻辑是通用的。建议把分析结果落成CSV,方便进一步人工研判:按源IP聚合,统计每个IP的可疑请求数和特征命中情况。

日志分析有一个天然局限:访问日志通常不记录完整的响应头,所以deleteMe响应特征拿不到。要弥补这个缺口,可以在抓包侧针对可疑IP做会话级别的流量留存,或者改用全流量解析。


4. 防御策略:从升级到纵深防御

4.1 升级与密钥替换:根治方案

防御这个漏洞最根本的手段只有两个:升级Shiro版本、替换默认密钥。两者缺一不可。

升级到修复版本(1.2.5及以上)是基础条件,它能拦截一部分早期利用方式,但仅靠升级并不够。如果升级后仍然使用默认密钥或一个公开的自定义密钥,攻击者换一个密钥值照常能打进。实际排查中,很多系统升级后因为配置文件没改,默认密钥依然生效,这类系统在攻击者眼里和没升级没有区别。

密钥替换的正确姿势:生成一个随机的128位AES密钥,用Base64编码后放到配置文件中。生成方法在操作系统里就能完成:

# 生成随机密钥并转为Base64 python3 -c "import os, base64; print(base64.b64encode(os.urandom(16)).decode())"

随机密钥要保存到安全的位置,比如环境变量或密钥管理服务,不要写死在代码仓库里。如果多个服务共用同一套Shiro配置,每个生产环境应该使用独立的密钥,避免一个环境泄露导致全部环境沦陷。

注意一点:替换密钥会导致所有已登录用户需要重新登录,因为旧的rememberMe Cookie无法用新密钥解密。上线密钥更换操作时,要选择业务低峰期执行,并且通过公告通知用户重新登录。

4.2 应用层加固:框架配置的常见误区

代码和配置层面的加固容易被忽视,说几个实际踩过的坑。

第一个坑是密钥硬编码在代码里。有些开发者图省事,直接在Java代码中写:

private static final byte[] cipherKey = Base64.decode("xxxxxxxxxxxxxxxxxxxxxxxxxxxx");

这样做的风险在于:代码仓库一旦泄露,密钥也就泄露了。更隐蔽的问题是,有些团队的代码仓库是内部共享的,外包人员、离职员工都可能接触过源码路径。正确的做法是把密钥放在配置文件或环境变量中,代码只负责读取。

第二个坑是依赖版本混乱。很多老项目用的Shiro版本是间接依赖引入的,比如通过某个第三方框架带进来的,项目本身的pom文件里没有直接声明Shiro版本。升级时只改了自己声明的版本,实际跑的还是旧版本。排查时需要检查依赖树,把传递依赖里的Shiro版本也找出来,使用Maven命令查看依赖树:

mvn dependency:tree -Dincludes=org.apache.shiro

第三个坑是只改了密钥但没测试。密钥替换后要完整回归测试登录流程,特别是有单点登录集成、移动端自动登录、小程序会话恢复这些依赖RememberMe的场景。我见过替换密钥后忘记同步到负载均衡后端的多节点集群,导致部分节点还能用旧密钥,流量随机打过去表现不一致,排查了半天。

4.3 网络层与主机层兜底

应用层的加固是第一道防线,但永远不要把鸡蛋放在一个篮子里。网络层和主机层的兜底能在应用层被绕过时提供第二道、第三道屏障。

网络层防护核心在于“过滤+限速”:

  • 在WAF或API网关上按照流量检测规则阻断超长异常Cookie请求。
  • 对同一源IP的异常Cookie请求频率做限速,触发阈值后临时封禁一段时间。
  • 对Cookie总大小设置上限,超出直接拦截。HTTP协议本身允许长Cookie,但业务完全不需要超过2KB的rememberMe值,这个限制对正常业务影响极小。
  • 封禁策略要有白名单机制,避免误伤办公网出口IP和API调用方。

主机层防护关注运行时的异常行为:

  • 部署主机入侵检测(HIDS),关注Java进程是否异常启动子进程,特别是/bin/sh、cmd.exe这类进程。
  • 关注Java进程的JVM参数、网络连接、文件写入是否出现异常。
  • 敏感目录(如/tmp、/var/tmp)出现可疑的jar包或class文件要第一时间告警。

纵深防御的效果是叠加的:攻击者即使绕过WAF,在主机层的进程监控下也会暴露;即使主机层没发现,留存的流量证据也能支撑事后溯源。


5. 常见误判与排查实录

5.1 误报场景分析与处置

流量检测规则上线后,误报是必然要面对的。Shiro反序列化检测有几类常见的误报场景,一一说清楚。

第一类:正常业务大Cookie。某个系统在用户对象中缓存了大量权限点,正常登录用户的rememberMe Cookie达到了近2000字符。这类流量会被长度阈值命中,但解码后内容是正常的用户对象,没有命令执行特征。处置方式是做白名单处理:对特定业务路径或特定用户对象指纹放行,同时保留日志记录。

第二类:多Cookie合并。部分Web框架会把多个Cookie值通过逗号拼接放在一个Header里,导致解析出的“rememberMe值”包含其他Cookie内容,长度虚高。比如响应头长这样:rememberMe=abc, JSESSIONID=xyz,如果正则提取不当会把整段都当成rememberMe。处置方式是修正提取规则,严格限定Cookie边界。

第三类:URL编码混淆。有些请求会把Cookie值做URL编码,日志里显示为超长百分号编码字符串。这类请求解码前后长度差异大,规则里要做两次解码再判断。

误报处置的通用原则:规则负责发现问题,人工负责判断定性。自动化封禁策略不要一级告警直接封禁,要设计分级处置:

  • 低危(仅长度异常):记录日志,观察后续行为。
  • 中危(长度异常+序列化特征):限制请求频率,加入观察名单。
  • 高危(长度异常+序列化特征+命令特征):立即阻断并告警。

5.2 漏报场景与绕过方式

只谈误报不提漏报是不负责任的。攻击者也在研究检测规则,有几个常见的绕过思路需要防御方知道。

长度绕过:某些极简Payload利用链可以压缩到较小体积,Base64后刚好卡在检测阈值之下。应对思路是降低阈值的同时,对全部Java序列化特征做匹配,而不是只盯超长样本。这样会有更多误报,但配合命令特征综合评分可以把漏报压下来。

Base64变体:部分工具支持自定义Base64编码方式,比如调整编码表、添加随机填充。这会直接绕过基于标准Base64解码的检测逻辑。应对思路是同时保留原始Cookie样本,在威胁狩猎阶段使用多引擎解码尝试。

特征串混淆:命令执行的关键词如whoami、/bin/sh可以被编码或拆分拼接,让特征匹配失效。这属于通用反混淆问题,没有银弹,只能在规则维护中持续补充新特征,同时依赖异常检测模型发现离群行为。

了解绕过思路是为了完善检测,而不是提供绕过教程。在具体安全实践里,我始终建议团队把重心放在“检测覆盖广、误报可治理、处置有分级”三个方向上,而不是盲目追求单条规则的完美精确。

5.3 应急排查步骤速查表

如果确认目标系统存在Shiro反序列化风险,或者已经出现攻击流量,按下面顺序做紧急处置:

步骤操作目的
1确认Shiro版本与密钥配置判断是否在受影响范围
2在访问日志/流量系统中检索所有超长rememberMe请求圈定攻击源和受影响入口
3检查响应日志中是否存在异常回显判断攻击是否成功
4在主机侧检查Java进程的子进程、JVM参数、敏感文件确认是否已经落地命令执行
5对可疑样本做离线分析还原攻击意图和利用链类型,为后续加固提供依据
6升级Shiro版本并替换密钥根除漏洞
7发布强制重新登录公告让失陷会话全部失效
8部署流量检测规则并持续监控防止绕过和二次攻击

第4步容易被忽略。很多团队处理这类告警只看了流量就收工,实际攻击可能已经打穿。Java反序列化漏洞一旦利用成功,攻击者通常会立即执行信息收集命令,留下大量痕迹。第一时间做主机侧排查是最关键的止损动作。


最后分享一点个人体会。CVE-2016-4437已经公开多年,但现在扫描公网和内网仍然能批量发现受影响系统,根本原因不是厂商没修复,而是大量老系统的维护节奏跟不上。对于防御方来说,这类“老漏洞”的价值恰恰在于特征足够稳定:默认密钥固定、Payload结构固定、流量特征明显,只要把检测规则和维护机制做到位,攻击成本会大幅上升,绝大部分脚本小子和批量扫描就会自动离开。流量检测是这个环节里成本最低、见效最快的一层,值得每个团队认真落地。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 15:13:05

机器学习评价指标实战指南:分类、回归与排序全解析

新开一个机器学习流程的实操系列&#xff0c;第一篇先聊评价指标。在真实项目里摸爬滚打久了你会发现&#xff0c;指标这个事往往不是“选一个数”这么简单&#xff0c;它决定了你后续所有调参往哪个方向使劲、模型什么时候能宣布达标、以及最后和业务方对齐时用什么话术。同一…

作者头像 李华
网站建设 2026/10/20 15:12:52

银行数据库国产化替换实战:从Oracle迁移到GBase的完整链路

把数据架构整体搬一遍家&#xff0c;无论放在哪个行业都不是小事&#xff0c;放在银行这种对一致性、可用性要求极高的场景里&#xff0c;更是牵一发动全身。最近我刚好深度参与了某农商银行&#xff08;以下按惯例以“某农商银行”代称&#xff09;的全栈数据库国产化替换项目…

作者头像 李华
网站建设 2026/10/20 15:12:25

AI生成代码时代的技术债务:度量、治理与还债实践

1. AI生成代码之后&#xff0c;技术债务的形态变了去年我参与排查过一起线上事故&#xff0c;最后定位到的问题代码&#xff0c;组里没人能说清楚它是谁写的、为什么这么写——只有一条孤零零的注释写着“根据某个需求调整逻辑”&#xff0c;而那个需求文档早在半年前就归档了。…

作者头像 李华
网站建设 2026/10/20 15:12:01

WorkBuddy数据转DSH格式:字段映射与自动化转换脚本实战

最近在给一个团队做数据整理&#xff0c;遇到一个挺典型的场景&#xff1a;团队一直用 WorkBuddy 记录任务和工时&#xff0c;积累了好几百条工作记录&#xff0c;但下游的报表系统只接受 DSH 格式的导入文件。一开始大家想的是从 WorkBuddy 导出 Excel 再手工改&#xff0c;结…

作者头像 李华
网站建设 2026/10/20 15:12:00

context-mode实战:大模型上下文管理设计与调优

最近和几个做 AI 应用的朋友聊天&#xff0c;几乎每个人都提到同一个词&#xff1a;context-mode。这个词在不同语境里含义不太一样&#xff0c;但大家苦恼的是同一件事——模型本身没有记忆&#xff0c;可业务偏偏是强状态的。我最早遇到 context-mode&#xff0c;是在做一个带…

作者头像 李华
网站建设 2026/10/20 15:10:57

MSTP协议原理与配置实践:多实例实现VLAN负载均衡与链路冗余

“MSTP原理”这个话题&#xff0c;光是这四个字母就能让不少刚接触交换网络的人犯迷糊。它同时是“多业务传送平台&#xff08;Multi-Service Transport Platform&#xff09;”和“多生成树协议&#xff08;Multiple Spanning Tree Protocol&#xff09;”的缩写&#xff0c;本…

作者头像 李华