我有一个如下所示的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个未屏蔽受保护的数据。

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

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

提前致谢。

最佳答案

不知道这是否有帮助。但是我会用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 - 在Java中屏蔽XML标签值的问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39635769/

10-09 13:46