stg*_*stg 4 dialog web-inf primefaces jsf-2
我使用Primefaces DialogFramework与
我的问题是,如果用户知道我的对话框的位置,他可以直接通过URL访问它.我不希望这是可能的,所以我认为它可以将对话框放在我的web-app的WEB-INF文件夹中,但是现在,如果我想打开对话框,我会得到一个FileNotFound-Exception.
如果我的对话框位于某个常规文件夹中,则可以正常工作
RequestContext.getCurrentInstance().openDialog("/myfolder/mydialog");
// this works as expected
Run Code Online (Sandbox Code Playgroud)
但如果它位于WEB-INF中,则它不再起作用
RequestContext.getCurrentInstance().openDialog("/WEB-INF/mydialog",options,null);
// this is causing a fileNotFoundException
Run Code Online (Sandbox Code Playgroud)
我也尝试为此设置导航规则faces-config
但是再次没有成功
<navigation-case>
<from-outcome>mydialog</from-outcome>
<to-view-id>/WEB-INF/mydialog.xhtml</to-view-id>
<redirect />
</navigation-case>
Run Code Online (Sandbox Code Playgroud)
我如何打开位于WEB-INF文件夹中的对话框,或者根本不可能?提前致谢
不幸的是,将PrimeFaces对话框架对话框放入/WEB-INF
以防止直接访问确实不起作用.对话框完全在客户端加载.在打开对话框的POST请求中,JSF/PrimeFaces返回一个oncomplete
脚本,其中包含对话框的(public!)URL到JavaScript/jQuery,后者又显示了一个基本对话框模板,<iframe>
其URL设置为对话框URL,反过来加载内容.实际上,正在发送2个请求,第一个是获取对话框的URL,第二个是根据该URL中的URL获取对话框的内容<iframe>
.
/WEB-INF
如果没有回退到"传统"对话框方法<p:dialog>
和通过JS/CSS进行条件显示,就无法保持对话框的存在.如果请求来自a <iframe>
,则服务器端也无法根据某些标头进行验证,以便可以简单地阻止所有其他标头.你最接近的赌注是referer
标题,但这可能是欺骗性的.
最小化滥用的一种方法是在请求对话时检查pfdlgcid
请求参数(由...标识Constants.DIALOG_FRAMEWORK.CONVERSATION_PARAM
)的存在.PrimeFaces即将表示"会话ID"的请求参数附加到对话URL.假设所有对话框都存储在一个文件夹中/dialogs
,那么你可以使用一个简单的servlet过滤器完成这项工作.这是一个启动示例,在/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.
}
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
但是,滥用者可能不是那么愚蠢并且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;
}
Run Code Online (Sandbox Code Playgroud)
然后将PrimeFaces DialogNavigationHandler
源代码复制到您自己的包中,并在第62行之后添加以下行:
DialogFilter.getIds((HttpServletRequest) context.getExternalContext().getRequest()).add(pfdlgcid);
Run Code Online (Sandbox Code Playgroud)
替换<navigation-handler>
在faces-config.xml
用定制的一个.
最后,改变方法中的if
条件DialogFilter#doFilter()
如下:
if (getIds(request).contains(id)) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
现在,这可以防止滥用者尝试使用随机ID打开对话框.但是,这并不会阻止滥用者通过在打开对话框<iframe>
后立即复制确切的URL 来尝试打开对话框.鉴于PrimeFaces对话框架的工作方式,没有办法防止这种情况发生.pfdlgcid
当对话框即将返回父级时,您最多可以从会话中删除该值.但是,当纯JS意味着关闭对话框时,这也被绕过了.
总而言之,如果你真的,真的,想要避免最终用户能够单独打开对话框,那么你就无法绕过"传统" <p:dialog>
方法.