MessagePostProcessor 可在发送前加解密,但仅限内存中消息体和头信息;不可修改routingKey等路由元数据;加解密须在postProcessMessage中实现,并显式设置contentType及contentLength。
MessagePostProcessor 能不能在发送前做加解密
能,但必须明确:它只作用于 convertandsend 或 send 方法调用时的「内存中消息对象」,不涉及网络传输层或 broker 端行为。加解密逻辑必须放在 postprocessmessage 里,且只能处理消息体(message.getbody())和头信息(message.getmessageproperties().getheaders()),不能修改 routingkey、exchange 等路由元数据。
为什么不能在 MessageConverter 里统一加解密
因为 MessageConverter 负责对象 ↔ 字节数组转换,而加解密是业务安全层动作,需与 traceId、权限标记等上下文强绑定。若混入 Converter:
- 加密逻辑无法感知当前线程 MDC 中的
traceId或用户 ID,导致链路追踪断裂 - 不同交换机/队列可能要求不同加解密策略(如内网直连不加密、跨域消息 AES-GCM 加密),Converter 无法按路由动态决策
- 一旦加密失败抛异常,
MessageConverter的错误堆栈会掩盖真实业务上下文,排查困难
加解密时 body 和 contentType 的配合要点
加解密后必须显式设置 contentType,否则消费者端 SimpleMessageConverter 可能因 content-type 不匹配拒绝解析:
- 加密前:检查
message.getMessageProperties().getContentType(),保留原始值(如"application/json") - 加密后:调用
message.getMessageProperties().setContentType("application/octet-stream"),避免消费者误判为文本 - 解密方需约定好:收到
application/octet-stream就先解密,再按原始contentType解析(该值应存入 header,如"original-content-type")
示例片段:
message.getMessageProperties().getHeaders().put("original-content-type", "application/json");
message.getMessageProperties().setContentType("application/octet-stream");
message.setBody(encrypt(message.getBody()));
常见踩坑:流式加解密导致 Body 被读空
不要在 postProcessMessage 中直接对 message.getBody() 做 InputStream 操作——它返回的是 byte[],不是流。若你封装了类似 AesUtils.encrypt(InputStream) 的工具方法,传入 new ByteArrayInputStream(message.getBody()) 是安全的;但若误写成 request.getInputStream()(来自 HTTP 请求),就完全跑偏了。
更隐蔽的问题是:加密后未重置 contentLength,导致 RabbitMQ 认为消息体长度异常,部分客户端(如某些 Python AMQP 库)会静默丢弃。
务必补上:
message.getMessageProperties().setContentLength(message.getBody().length);
这个字段容易被忽略,但它直接影响 Broker 对消息完整性的校验。










