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@gmail.com","lastname":"Doe","firstname":"Über"}'};
Autobeanを使用したデコードは正常に機能しますが、文字üは正しく表示されませんが、HTMLはエスケープされます(Über
)。
この関数を使用するとencodeForJavaScript()
、出力は次のようになります。
var data = {'user':'{"email":"john.doe@gmail.com","lastname":"Doe","firstname":"\\xDCber"}'};
JSON文字列をデコードしようとすると、奇妙な問題が発生します。開発モード/ホストモードでは、デコードは正常に機能し、ウムラウトが正しく表示されます。ただし、本番モードでコードを実行するとすぐに、キャッチされない例外が発生します。
java.lang.IllegalArgumentException: Error parsing JSON: SyntaxError: Unexpected token x
{"email":"john.doe@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)
私は次の解決策を考えることができます:
- 入力検証(データがデータベースに保存されている場合)のみに依存し、出力エンコーディングを削除します。しかし、それは推奨されるアプローチではありません。
- ウムラウトを通常のASCII文字(ü=> ue)に置き換え、出力エンコーディングを引き続き使用します
- 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のようですfindOriginalDeclaringClass
CompilingClassLoader.java
declaringClasses