5

私は Primefaces DialogFrameworkを使用しています

  • プライムフェイス 5.0
  • モハラ 2.1.27
  • Glassfish 3.1.2.2 ビルド 5

私の問題は、ユーザーがダイアログの場所を知っている場合、URL を介して直接アクセスできることです。それを可能にしたくないので、ダイアログをWebアプリのWEB-INFフォルダーに入れることができると思っていましたが、今、ダイアログを開こうとすると、FileNotFound-Exceptionが発生します。

私のダイアログが通常のフォルダにある場合、正常に動作します

RequestContext.getCurrentInstance().openDialog("/myfolder/mydialog"); 
// this works as expected

しかし、それが WEB-INF にある場合は、もはや機能しません。

RequestContext.getCurrentInstance().openDialog("/WEB-INF/mydialog",options,null);
// this is causing a fileNotFoundException

また、これにナビゲーションルールを設定しようとしましたfaces-configが、成功しませんでした

<navigation-case>
    <from-outcome>mydialog</from-outcome>
    <to-view-id>/WEB-INF/mydialog.xhtml</to-view-id>
    <redirect />
</navigation-case>

WEB-INF フォルダにあるダイアログを開くにはどうすればよいですか? 前もって感謝します

4

1 に答える 1

10

残念ながら、直接アクセスを防ぐために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>場合は、「従来の」アプローチを回避することはできません。

于 2014-07-27T20:20:59.760 に答える