不幸的是,將PrimeFaces對話框框架對話框in /WEB-INF
in order to prevent direct access確實不起作用。對話框完全加載客戶端。在打開對話框的POST請求上,JSF/PrimeFaces返回一個oncomplete
腳本,其中包含對話框的(public!)URL到JavaScript/jQuery,後者又顯示一個基本對話框模板,其中的的URL被設置爲對話框URL ,然後加載內容。在效果中,正在發送2個請求,第一個獲取對話框的URL,第二個獲取基於中該URL的對話框內容。
沒有辦法保持/WEB-INF
中的對話框沒有回落到通過<p:dialog>
和通過JS/CSS的條件顯示的「傳統」對話方式。如果請求來自,那麼服務器端也無法根據某些標頭進行驗證,因此所有其他標識都可能會被阻止。您最接近的投注是referer
標題,但這可能是欺騙性的。
減少濫用的一種方法是在請求對話時檢查是否存在pfdlgcid
請求參數(由Constants.DIALOG_FRAMEWORK.CONVERSATION_PARAM
標識)。 PrimeFaces即將這個代表「對話ID」的請求參數附加到對話URL。假定所有的對話框存儲在一個文件夾/dialogs
中,那麼你可以用簡單的servlet filter來完成這項工作。下面是一個啓動示例,當請求/dialogs/*
而沒有pfdlgcid
請求參數時,將發送HTTP 400錯誤。
@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
值存儲在會話映射中,該映射又會在servlet過濾器中進行比較。
首先添加下面的方法將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;
}
然後copypaste的PrimeFaces DialogNavigationHandler
source code到自己的包和第62行後添加以下行:
DialogFilter.getIds((HttpServletRequest) context.getExternalContext().getRequest()).add(pfdlgcid);
與更換<navigation-handler>
在faces-config.xml
定製的。
最後,改變if
條件在DialogFilter#doFilter()
方法如下:
if (getIds(request).contains(id)) {
// ...
}
現在,這防止濫用者從嘗試與隨機ID打開對話框。但是,這不會阻止濫用者在打開對話框後立即通過複製準確的 URL來嘗試打開對話框。鑑於PrimeFaces對話框架的工作方式,無法防止這種情況發生。當對話框即將返回到父級時,最多可以從會話中刪除pfdlgcid
值。但是,當對話框以純JS方式關閉時,這也被繞過。
總而言之,如果真的,真的是,想要避免最終用戶能夠單獨打開對話框,那麼您不能繞過「傳統」<p:dialog>
方法。