【问题标题】:Issue in masking XML tag value in java在 java 中屏蔽 XML 标记值的问题
【发布时间】:2017-01-30 20:07:10
【问题描述】:

我有一个如下所示的 XML 文件:

<Envelope>
<Body>
  <user1>
    <userId>userName</userId>
    <password>password</password>
    <creditCard>
        <creditCardNumber>12345678901234</creditCardNumber>
        <cvv>123</cvv>
    </creditCard>
  </user1>
  <user2>
    <userId>userName</userId>
    <password>password</password>
    <creditCard>
        <creditCardNumber>12345678901234</creditCardNumber>
        <cvv>123</cvv>
    </creditCard>
  </user2>
</Body>
</Envelope>

我有一个 java 代码用于将 xml 事务记录到某些服务器上以供将来参考。此 java 代码具有在登录之前屏蔽标签的某些字符或整个值的方法,因为不会泄露信用卡详细信息。

方法如下:

    public static String mask( String input, String[] tags, String maskPattern, String namespacePattern)
        throws Throwable
    {
        StringBuffer sb = new StringBuffer( input );
        encodedXML = false;
        if (sb.indexOf( "&gt;" ) > 0) {
            // XML is encoded
            gt = "&gt;";
            lt = "&lt;";
            encodedXML = true;
            // modify patterns for encoded xml
            maskPattern = "(&gt;)" + alphaNumericStuff + "+(&lt;)/";
            if (sb.indexOf( "&quot;" ) >= 0) {
                // There is a mix of double quotes and &quot; in this xml
                namespacePattern = mixedEncodingAlphaNumericStuff + "*";
            }
        }
        for (int i = 0; i < tags.length; i++) {
            // do a quick check to see if the tag is in the string to reduce excessive string creation
            if (sb.indexOf( tags[i] ) < 0) {
                continue;
            } else {
                sb = maskElementValue( sb, tags[i],maskPattern, namespacePattern );
            }
        }
        return sb.toString();
    }




private static StringBuffer maskElementValue( StringBuffer sb, String tag, String maskPattern,String namespacePattern)
    {
        // Pattern p = Pattern.compile( tag + maskPattern ); doesn't take namespace into account
        Pattern p = Pattern.compile( tag + namespacePattern + maskPattern );
        Matcher m = p.matcher( sb.toString() );
        StringBuffer tempSB = new StringBuffer();
        String namespaceStr = "";
        while (m.find()) {
            namespaceStr = m.group().substring( tag.length(), m.group().indexOf( gt ) );
            // Added full masking for username and password including last 4 characters
            if (tag.equalsIgnoreCase( "username" ) || tag.equalsIgnoreCase( "password" )) {
                m.appendReplacement( tempSB, tag + namespaceStr + gt + xOut( new StringBuffer( m.group().substring( tag.length() + namespaceStr.length() + gt.length() ) ), true ) );
            } else {
                m.appendReplacement( tempSB, tag + namespaceStr + gt + xOut( new StringBuffer( m.group().substring( tag.length() + namespaceStr.length() + gt.length() ) ), false ) );
            }
        }
        m.appendTail( tempSB );
        return tempSB;
    }



private static String xOut( StringBuffer sb, boolean maskAll )
    {
        int dataSize = sb.toString().trim().length() - 1 - lt.length();
        if (!maskAll && dataSize > 4) {
            if (sb.indexOf( "&lt;" ) > 0 || sb.indexOf( "<" ) > 0) {
                StringBuffer tempmaskSB = new StringBuffer( sb.substring( 0, sb.indexOf( "&lt;" ) ) );
                dataSize = tempmaskSB.length();
            }
            // Don't mask last 4 digit
            for (int i = 0; i < dataSize - 4; i++) {
                sb.setCharAt( i, 'X' );
            }
        } else {
            if (sb.indexOf( "&lt;" ) > 0 || sb.indexOf( "<" ) > 0) {
                StringBuffer tempmaskSB = new StringBuffer( sb.substring( 0, sb.indexOf( "&lt;" ) ) );
                dataSize = tempmaskSB.length();
            }
            // Mask all
            for (int i = 0; i < dataSize; i++) {
                sb.setCharAt( i, 'X' );
            }
        }
        return sb.toString();
    }

我将 xml 作为字符串传递给方法和要屏蔽的标签数组。如果是用户名和密码,它们应该被完全屏蔽,并且数组中的其他标签应该被屏蔽,除了最后 4 个字符。

现在的问题是某些交易没有发生屏蔽。当我们完成负载测试时,18000 个事务中有 12 个没有屏蔽受保护的数据。

在某些情况下,用户 1 的详细信息会被屏蔽,但用户 2 的详细信息不会在同一事务中被屏蔽。

谁能帮助我理解为什么会这样?以前有人遇到过这样的问题吗?

提前致谢。

【问题讨论】:

  • 我会强烈敦促您停止进行所有这些字符串操作。要处理 XML,请使用 XML API。 (另外,使用StringBuilder 而不是StringBuffer,除非你真的,真的需要同步......)
  • 我很确定在这种情况下可以使用xslt & StAX
  • 您好 Jon,您能否提供一些有关如何使用 XML API 的参考资料。

标签: java xml masking stringbuffer


【解决方案1】:

不确定这是否有帮助。但我会用jsoup

做掩蔽部分

例子:

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.parser.Parser;
import org.jsoup.select.Elements;

public class Mask {
    static String xml =    "<Envelope>\n" +
                "<Body>\n" +
                "  <user1>\n" +
                "    <userId>userName</userId>\n" +
                "    <password>password</password>\n" +
                "    <creditCard>\n" +
                "        <creditCardNumber>12345678901234</creditCardNumber>\n" +
                "        <cvv>123</cvv>\n" +
                "    </creditCard>\n" +
                "  </user1>\n" +
                "  <user2>\n" +
                "    <userId>userName</userId>\n" +
                "    <password>password</password>\n" +
                "    <creditCard>\n" +
                "        <creditCardNumber>12345678901234</creditCardNumber>\n" +
                "        <cvv>123</cvv>\n" +
                "    </creditCard>\n" +
                "  </user2>\n" +
                "</Body>\n" +
                "</Envelope>";
    public static void main (String[]args){
        Document doc = Jsoup.parse(xml, "", Parser.xmlParser());
        Elements toMaskCompletely = doc.select("userId,password");
        Elements toMaskPartially = doc.select("creditCardNumber");
        for(Element ele : toMaskCompletely){
            ele.text("XXXXX");
        }
        for(Element ele : toMaskPartially){
           ele.text("XXXXXXXX"+ele.text().substring(ele.text().length()-4));
        }
        System.out.println(doc.toString());
    }
  }

【讨论】:

  • 很遗憾我们使用的java版本是1.4。我怀疑 JSoup 是否支持 java 1.4。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-05
  • 1970-01-01
  • 2017-04-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多