最近账户老被锁,每天上班第一件事就是找IT解锁。IT终于也烦了,给了一个链接,告诉我可以通过回答入职时填的密码提示问题自行解锁。今天一来开电脑,意料之中的”You account had been locked out, please contact …”。兴冲冲的打开解锁链接,看到密码提示问题时,不由傻眼。不知道当初怎么想的,居然用的全是中文问题。看着下面这一串串问题编码,暗自嘲讽,这才是最安全的密码提示问题,(自个儿都看不懂了)。

父亲的名字

母亲的名字

我的名字

妹妹的名字

懊恼归懊恼,问题总得解决,Google了一把如何解码Html字符。StackOverFlow没有让我失望http://stackoverflow.com/questions/994331/java-how-to-decode-html-character-entities-in-java-like-httputility-htmldecode

嗖嗖的建了一个Maven工程,加入commons-lang的依赖。

<dependency>
    <groupId>commons-lang</groupId>
    <artifactId>commons-lang</artifactId>
    <version>2.6</version>
    <type>jar</type>
    <scope>compile</scope>
</dependency>

写个测试类来试试。

public class DecodeHtml {

    public static void main(String args[]) {

        System.out.println(StringEscapeUtils
                .unescapeHtml("&#29238;&#20146;&#30340;&#21517;&#23383;"));

        System.out.println(StringEscapeUtils
                .unescapeHtml("&#27597;&#20146;&#30340;&#21517;&#23383;"));

        System.out.println(StringEscapeUtils
                .unescapeHtml("&#25105;&#30340;&#21517;&#23383;"));

        System.out.println(StringEscapeUtils
                .unescapeHtml("&#22969;&#22969;&#30340;&#21517;&#23383;"));

    }

}

输出结果:

image

至此算是解码成功了,那么它又是如何解码的呢?过了一下源代码。

StringEscapeUtils类中无论是编码escapeHtml,还是解码unescapeHtml,到最后都是调用Entities.HTML40中的escape或unescape方法。追踪到Entities类,几段关键代码:

静态块初始化HTML40成员变量。

static {
    Entities html40 = new Entities();
    fillWithHtml40Entities(html40);
    HTML40 = html40;
}

添加Entities,怎么感觉有点像密码破译,总得有个样本,有个依据,不然你鬼画桃符一番,谁看得懂。

static void fillWithHtml40Entities(Entities entities) {
    entities.addEntities(BASIC_ARRAY);
    entities.addEntities(ISO8859_1_ARRAY);
    entities.addEntities(HTML40_ARRAY);
}

最后再依据“密码”进行破译。

public void unescape(Writer writer, String str) throws IOException {
    int firstAmp = str.indexOf('&');
    if (firstAmp &lt; 0) {
        writer.write(str);
        return;
    } else {
        doUnescape(writer, str, firstAmp);
    }
}