如何在SAP Hybris中对所有API请求与响应进行加解密?
除了你考虑的过滤器解密、自定义清理器加密方案,还有以下几种成熟的实现方式:
1. 拦截器(Interceptor)方案
和过滤器思路类似,但更贴近业务逻辑层(比如Spring生态中的HandlerInterceptor)。在请求到达控制器前,通过preHandle方法解密请求体;在控制器处理完生成响应后,通过postHandle方法加密响应体。这种方式能更精准地控制请求/响应的处理时机,且可以获取到Spring上下文的相关信息。
示例代码片段(Spring环境):
public class EncryptInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 解密请求体逻辑 String encryptedBody = request.getReader().lines().collect(Collectors.joining()); String decryptedBody = decrypt(encryptedBody); // 替换请求体,供后续控制器使用 request = new HttpServletRequestWrapper(request) { @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new StringReader(decryptedBody)); } }; return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 加密响应体逻辑 EncryptResponseWrapper responseWrapper = new EncryptResponseWrapper(response); String encryptedResponse = encrypt(responseWrapper.getResponseBody()); response.getWriter().write(encryptedResponse); } }
2. 消息转换器(MessageConverter)方案
直接在请求的序列化/反序列化阶段处理加密解密,比如自定义MappingJackson2HttpMessageConverter(针对JSON格式),重写readInternal(解密请求体并反序列化为对象)和writeInternal(序列化对象后加密响应体)方法。这种方式无需额外处理请求/响应的流转,完全嵌入Spring的消息转换流程,代码侵入性更低。
示例代码片段:
public class EncryptJacksonConverter extends MappingJackson2HttpMessageConverter { @Override protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { // 解密请求体 String encryptedBody = StreamUtils.copyToString(inputMessage.getBody(), StandardCharsets.UTF_8); String decryptedBody = decrypt(encryptedBody); // 反序列化 return super.getObjectMapper().readValue(decryptedBody, clazz); } @Override protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { // 序列化对象 String jsonBody = super.getObjectMapper().writeValueAsString(object); // 加密后输出 String encryptedBody = encrypt(jsonBody); outputMessage.getBody().write(encryptedBody.getBytes(StandardCharsets.UTF_8)); } }
3. 网关层统一处理
如果系统中有API网关(如Spring Cloud Gateway、Zuul),可以在网关层面实现全局的请求解密和响应加密。这种方式完全解耦业务服务,业务代码无需做任何加密相关修改,所有加密解密逻辑都集中在网关处理,便于统一维护和调整。
核心思路是通过网关的全局过滤器(GlobalFilter)拦截所有请求,解密请求体后转发给后端服务;接收后端响应后,加密响应体再返回给客户端。
4. 注解驱动的AOP切面方案
自定义一个加密注解(如@ApiEncrypt),通过AOP环绕通知,对标注了该注解的接口方法进行处理:在方法执行前解密入参(如果是请求体参数),在方法执行后加密返回结果。这种方式灵活性极高,可以针对特定接口或方法开启加密,而非全局强制加密。
示例代码片段:
@Aspect @Component public class EncryptAspect { @Autowired private ObjectMapper objectMapper; @Around("@annotation(com.example.ApiEncrypt)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { // 解密入参 Object[] args = joinPoint.getArgs(); if (args.length > 0) { String encryptedArgs = objectMapper.writeValueAsString(args[0]); String decryptedArgs = decrypt(encryptedArgs); args[0] = objectMapper.readValue(decryptedArgs, args[0].getClass()); } // 执行原方法 Object result = joinPoint.proceed(args); // 加密返回结果 String encryptedResult = encrypt(objectMapper.writeValueAsString(result)); return objectMapper.readValue(encryptedResult, result.getClass()); } }
内容的提问来源于stack exchange,提问作者pradeep murugan

