残念ながら、直接アクセスを防ぐためにPrimeFaces ダイアログ フレームワーク ダイアログを/WEB-INF
配置しても、実際には機能しません。ダイアログは完全にクライアント側で読み込まれます。ダイアログを開く POST 要求で、JSF/PrimeFaces は、ダイアログoncomplete
の (パブリック!) URL を含むスクリプトを JavaScript/jQuery に返します。これにより<iframe>
、URL がダイアログ URL に設定されている基本的なダイアログ テンプレートが表示されます。次に、コンテンツをロードします。実際には、2 つの要求が送信されています。1 つ目はダイアログの URL を取得するためのもので、2 つ目は .xml 内のその URL に基づいてダイアログのコンテンツを取得するためのもの<iframe>
です。
JS/CSS を/WEB-INF
介した「従来の」ダイアログ アプローチと条件付き表示に戻らない限り、ダイアログを保持する方法はありません。<p:dialog>
また、サーバー側では、リクエストが からのものであるかどうかを一部のヘッダーに基づいて検証する方法がない<iframe>
ため、他のすべてのヘッダーは単純にブロックされる可能性があります。あなたの最も近い賭けはreferer
ヘッダーですが、これはなりすましの可能性があります。
悪用を最小限に抑える 1 つの方法は、ダイアログが要求されているときにpfdlgcid
要求パラメーター ( で識別される) の存在をチェックすることです。Constants.DIALOG_FRAMEWORK.CONVERSATION_PARAM
つまり、PrimeFaces は、「会話 ID」を表すこの要求パラメーターをダイアログ URL に追加します。すべてのダイアログがフォルダーに格納されていると仮定すると、単純なサーブレット フィルター/dialogs
を使用してジョブを実行できます。がリクエスト パラメータなしでリクエストされたときに HTTP 400 エラーを送信するキックオフの例を次に示します。/dialogs/*
pfdlgcid
@WebFilter("/dialogs/*")
public class DialogFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String id = request.getParameter(Constants.DIALOG_FRAMEWORK.CONVERSATION_PARAM);
if (id != null) {
chain.doFilter(req, res); // Okay, just continue request.
}
else {
response.sendError(HttpServletResponse.SC_BAD_REQUEST); // 400 error.
}
}
// ...
}
ただし、乱用者はそれほど愚かではなくpfdlgcid
、通常のフロー中に要求パラメーターを発見し、ランダムな値であっても、そのパラメーターを提供するときにダイアログを個別に開くことができる場合があります。実際のpfdlgcid
値を既知のものと比較することを考えました。PrimeFaces のソース コードを確認しましたDialogNavigationHandler
が、残念ながら、PrimeFaces はこの値をセッションのどこにも保存していません。DialogNavigationHandler
値をセッションマップに保存するカスタム実装を提供する必要がありpfdlgcid
ます。これは、サーブレットフィルターでも比較されます。
まず、次のメソッドを に追加しますDialogFilter
。
public static Set<String> getIds(HttpServletRequest request) {
HttpSession session = request.getSession();
Set<String> ids = (Set<String>) session.getAttribute(getClass().getName());
if (ids == null) {
ids = new HashSet<>();
session.setAttribute(getClass().getName(), ids);
}
return ids;
}
次に、PrimeFacesDialogNavigationHandler
ソース コードを自分のパッケージにコピーペーストし、62 行目の後に次の行を追加します。
DialogFilter.getIds((HttpServletRequest) context.getExternalContext().getRequest()).add(pfdlgcid);
カスタマイズしたものに交換して<navigation-handler>
ください。faces-config.xml
最後に、メソッドのif
条件を次のように変更します。DialogFilter#doFilter()
if (getIds(request).contains(id)) {
// ...
}
これにより、乱用者がランダムな ID でダイアログを開こうとするのを防ぎます。<iframe>
ただし、これは、悪用者がダイアログを開いた直後に正確な URL をコピーペーストしてダイアログを開こうとすることを防ぐものではありません。PrimeFaces ダイアログ フレームワークがどのように機能するかを考えると、それを防ぐ方法はありません。pfdlgcid
ダイアログが親に戻ろうとしているときに、せいぜいセッションから値を削除できます。ただし、純粋な JS 手段によってダイアログが閉じられると、これもバイパスされます。
全体として、エンドユーザーがダイアログを個別に開けないようにしたい<p:dialog>
場合は、「従来の」アプローチを回避することはできません。