CXF使用内容过滤或屏蔽soap字段记录请求和响应

我想通过内容过滤记录来自某个特定端点的所有传入请求和响应。 即当我有这样的要求时:

   Apples Photo with some apples in it  anVzdCBhIHJhbmRvbSB0ZXh0DQpqdXN0IGEgcmFuZG9tIHRleHQNCmp1c3QgYSByYW5kb20gdGV4dA0KanVzdCBhIHJhbmRvbSB0ZXh0DQpqdXN0IGEgcmFuZG9tIHRleHQNCmp1c3QgYSByYW5kb20gdGV4dA0KanVzdCBhIHJhbmRvbSB0ZXh0DQp3b3csIGkgZGlkbid0IHRob3VnaHQgdGhhdCBhbnlvbmUgd291bGQgYmUgaW50ZXJlc3RlZCBpbiBkZWNvZGluZyB0aGlzLiBjb25ncmF0cyE=    

我想过滤它,以便它看起来像这样的日志

    Apples Photo with some apples in it hidden    

或完全删除m:照片元素。

我发现CXF有一些LoggingInInterceptor和LoggingOutInterceptor,我可以编写自己的拦截器来做到这一点。 然而,这将是一项工作要做,所以我的问题是:你知道更好,开箱即用的解决方案吗?

我有类似的问题,我需要在输入请求中屏蔽密码。 我对现有的LogginInterceptor和重写格式方法做了一些小改动,并添加了我的方法来掩盖密码。 这是一个例子

 public class CustomLogInInterceptor extends LoggingInInterceptor { @Override protected String formatLoggingMessage(LoggingMessage loggingMessage) { String str = loggingMessage.toString(); String output = maskPasswords(str); return(output); } private String maskPasswords(String str) { final String[] keys = { "password", "passwords" }; for (String key : keys) { int beginIndex = 0; int lastIndex = -1; boolean emptyPass = false; while (beginIndex != -1 && (beginIndex = StringUtils.indexOfIgnoreCase(str, key, beginIndex)) > 0) { beginIndex = StringUtils.indexOf(str, ">", beginIndex); if (beginIndex != -1) { char ch = str.charAt(beginIndex - 1); if (ch == '/') { emptyPass = true; } if (!emptyPass) { lastIndex = StringUtils.indexOf(str, "<", beginIndex); if (lastIndex != -1) { String overlay = "*"; String str2 = StringUtils.substring(str, beginIndex + 1, lastIndex); if (str2 != null && str2.length() > 1) { overlay = StringUtils.rightPad(overlay, str2.length(), "*"); str = StringUtils.overlay(str, overlay, beginIndex + 1, lastIndex); } } } if (emptyPass) { emptyPass = false; lastIndex = beginIndex + 1; } else { if (lastIndex != -1) { lastIndex = StringUtils .indexOf(str, ">", lastIndex); } } } beginIndex = lastIndex; } } return str; } } 

并在我的cxf-bean.xml中添加了custtom cxf logging bean

          

注意我已经使用Apache commons-lang3 jar进行字符串操作。 同样,您也可以使用响应


UPDATE

使用模式并使用属性使密钥可配置。

拦截器

 public class CustomLogInInterceptor extends LoggingInInterceptor { private static final String MASK_PATTERN = "<\\s*{}\\s*>(.*)|<\\s*name\\s*>\\s*{}\\s*\\s*<\\s*value\\s*>(.*)<"; private Pattern pattern; private String[] keys; public void init() { StringBuilder builder = new StringBuilder(); for (String str : keys) { builder.append(MASK_PATTERN.replace("{}", str)); builder.append("|"); } builder.setLength(builder.length()-1); pattern = Pattern.compile(builder.toString(), Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); } public void setKeys(String[] keys) { this.keys = keys; } @Override protected String formatLoggingMessage(LoggingMessage loggingMessage) { String output = maskPasswords(loggingMessage.toString()); return(output); } private String maskPasswords(String str) { Matcher matcher = pattern.matcher(str); final StringBuilder builder = new StringBuilder(str); while (matcher.find()) { int group = 1; while (group <= matcher.groupCount()) { if (matcher.group(group) != null) { for (int i = matcher.start(group); i < matcher.end(group); i++) { builder.setCharAt(i, '*'); } } group++; } } return builder.toString(); } } 

豆创作

    password accountId    

样本输入

   adffas dfsdf sdfsfs sdfsfsf 3434 password sdfsfs  password  123456    sdfsfs     

和输出

   adffas dfsdf ****** sdfsfsf **** password ******  password  ******    ******     

我编写了一个开源库,旨在有效地打印SOAP消息: xml-formatter-components-cxf 。 function包括:

  • XML的高性能重新格式化
  • 高级过滤选项
    • 最大文本和/或CDATA节点大小
    • 在文本和/或CDATA节点中重新格式化XML
    • 匿名化元素和/或属性内容
    • 删除子树

弹簧的完整配置参考 。

编辑:上面的库已经被重构为更通用的库 ,这对于大多数正常的用例来说可能更好,即没有用XML包装的XML。