【发布时间】: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( ">" ) > 0) {
// XML is encoded
gt = ">";
lt = "<";
encodedXML = true;
// modify patterns for encoded xml
maskPattern = "(>)" + alphaNumericStuff + "+(<)/";
if (sb.indexOf( """ ) >= 0) {
// There is a mix of double quotes and " 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( "<" ) > 0 || sb.indexOf( "<" ) > 0) {
StringBuffer tempmaskSB = new StringBuffer( sb.substring( 0, sb.indexOf( "<" ) ) );
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( "<" ) > 0 || sb.indexOf( "<" ) > 0) {
StringBuffer tempmaskSB = new StringBuffer( sb.substring( 0, sb.indexOf( "<" ) ) );
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