1

SpringバックエンドにアプリケーションGWTがあり、フロントエンドにアプリケーションがあります。ユーザーがログインすると、''index.jsp''はユーザー情報をjavascript変数として出力します。

私はAutoBeanFactoryユーザー情報をjsonとしてエンコードおよびデコードするために使用しています。
ユーザーは登録でき、ユーザー情報はデータベースに保存されるため、JSPページでユーザー情報をエスケープして、 OWASPXSSのチートシートを防止するようにしています。

エンコーディングを行うためにesapiライブラリを使用しています。サーバー側のコードは次のようになります。

public static String serializeUserToJson(CustomUser user) {
        String json;
        AppUserProxy appUserProxy = appUserFactory.appuser().as();
        appUserProxy.setFirstname(encoder.encodeForHTML(user.getFirstname()));
        appUserProxy.setLastname(encoder.encodeForHTML(user.getLastname()));
        AutoBean<AppUserProxy> bean = appUserFactory.appuser(appUserProxy);
        json = AutoBeanCodex.encode(bean).getPayload();
        return json;
    }

使っencodeForHTMLてみましたencodeForJavaScript()。これは通常の文字では問題なく機能しますが、ウムラウト文字(ü、ä、ö)を使用するとすぐに問題が発生します。

この関数を使用するとencodeforHTML()、javascript変数は次のようになります(名にはüがあることに注意してください)。

var data = {'user':'{"email":"john.doe&#x40;gmail.com","lastname":"Doe","firstname":"&Uuml;ber"}'};

Autobeanを使用したデコードは正常に機能しますが、文字üは正しく表示されませんが、HTMLはエスケープされます(&Uuml;ber)。

この関数を使用するとencodeForJavaScript()、出力は次のようになります。

var data = {'user':'{"email":"john.doe&#x40;gmail.com","lastname":"Doe","firstname":"\\xDCber"}'};

JSON文字列をデコードしようとすると、奇妙な問題が発生します。開発モード/ホストモードでは、デコードは正常に機能し、ウムラウトが正しく表示されます。ただし、本番モードでコードを実行するとすぐに、キャッチされない例外が発生します。

java.lang.IllegalArgumentException: Error parsing JSON: SyntaxError: Unexpected token x
{"email":"john.doe&#x40;gmail.com","lastname":"Doe","firstname":"\xDCber"}
    at Unknown.java_lang_RuntimeException_RuntimeException__Ljava_lang_String_2V(Unknown Source)
    at Unknown.java_lang_IllegalArgumentException_IllegalArgumentException__Ljava_lang_String_2V(Unknown Source)
    at Unknown.com_google_gwt_core_client_JsonUtils_throwIllegalArgumentException__Ljava_lang_String_2Ljava_lang_String_2V(Unknown Source)
    at Unknown.com_google_gwt_core_client_JsonUtils_safeEval__Ljava_lang_String_2Lcom_google_gwt_core_client_JavaScriptObject_2(Unknown Source)
    at Unknown.com_google_web_bindery_autobean_shared_impl_StringQuoter_split__Ljava_lang_String_2Lcom_google_web_bindery_autobean_shared_Splittable_2(Unknown Source)
    at Unknown.com_google_web_bindery_autobean_shared_AutoBeanCodex_decode__Lcom_google_web_bindery_autobean_shared_AutoBeanFactory_2Ljava_lang_Class_2Ljava_lang_String_2Lcom_google_web_bindery_autobean_shared_AutoBean_2(Unknown Source)
    at Unknown.com_gmi_nordborglab_browser_client_mvp_main_UserInfoPresenter_onBind__V(Unknown Source)

私は次の解決策を考えることができます:

  1. 入力検証(データがデータベースに保存されている場合)のみに依存し、出力エンコーディングを削除します。しかし、それは推奨されるアプローチではありません。
  2. ウムラウトを通常のASCII文字(ü=> ue)に置き換え、出力エンコーディングを引き続き使用します
  3. XSS文字をエスケープするが、ウムラウトはそのままにしておくライブラリを使用します。

フィードバックに感謝します

更新:Thomasの提案に基づいてJsoSplittable、JSNIからaを渡し、これをAutoBeanCodex.decode関数に渡します。本番モードでは正常に動作しますが、ホストモードでは次のNPEを取得します。

java.lang.NullPointerException: null
    at com.google.gwt.dev.shell.CompilingClassLoader$MyInstanceMethodOracle.findOriginalDeclaringClass(CompilingClassLoader.java:428)
    at com.google.gwt.dev.shell.rewrite.WriteJsoImpl.isObjectMethod(WriteJsoImpl.java:307)
    at com.google.gwt.dev.shell.rewrite.WriteJsoImpl.visitMethod(WriteJsoImpl.java:289)
    at com.google.gwt.dev.shell.rewrite.WriteJsoImpl$ForJsoInterface.visitMethod(WriteJsoImpl.java:228)
    at com.google.gwt.dev.asm.ClassAdapter.visitMethod(ClassAdapter.java:115)
    at com.google.gwt.dev.shell.rewrite.RewriteJsniMethods.visitMethod(RewriteJsniMethods.java:350)
    at com.google.gwt.dev.asm.ClassReader.accept(ClassReader.java:774)
    at com.google.gwt.dev.asm.ClassReader.accept(ClassReader.java:420)
    at com.google.gwt.dev.shell.rewrite.HostedModeClassRewriter.rewrite(HostedModeClassRewriter.java:251)
    at com.google.gwt.dev.shell.CompilingClassLoader.findClassBytes(CompilingClassLoader.java:1236)
    at com.google.gwt.dev.shell.CompilingClassLoader.findClass(CompilingClassLoader.java:1059)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

この例外の原因となるコードは次のとおりです。

private native final JsoSplittable getJsoUserdata() /*-{
    if (typeof $wnd.user   !== 'undefined')
        return $wnd.user;
    return null;
}-*/;

@Override
public JsoSplittable getUserdata() {
    JsoSplittable user = null;
    user = getJsoUserdata();
    if (user != null) {
       String payload = user.getPayload();
       Window.alert(payload);
    }
    return user;
}

Window.alert(payload)は、本番モードで正常に機能します。ホストモードでは、ステップインすると、の機能でuser.getPayload() NPEが取得されます。nullのようですfindOriginalDeclaringClassCompilingClassLoader.javadeclaringClasses

4

1 に答える 1

2

明示的に何かをエスケープするべきではありません。AutoBeansはすでにそれを行います。むしろ、何かをエスケープしたい場合は、内部ではなく、AutoBeanの出力をエスケープしますgetPayload()

問題は、AutoBeansがJSON.parse()可能な場合(パフォーマンスと安全性の両方の理由で)ネイティブを使用することです。これは、仕様に従って、出力\uNNNNの種類ではなく、エスケープの種類のみをサポートします。つまり、ESAPIには。が必要です。\xHHencodeForJavaScriptencodeForJSON

于 2012-05-03T10:44:27.547 に答える