我正在使用带有客户端状态保存的 MyFaces 2.2.3 + PrimeFaces
问完后如何防止在不同会话中重复使用 ViewState I was 由 BalusC 讲述,我可以inject my own CSRF代币 by 重写 from 渲染器,让该值成为 CSRF 令牌 ,
我正在寻找一种不会强迫我修改我的解决方案xhtml全部页面:)
BalusC 提出了一种更好的方法来防止 CSRF 攻击,方法是扩展ViewHandlerWrapper
,效果很好,我只需要修改一下restoreView
通过以下方式
public UIViewRoot restoreView(FacesContext context, String viewId) {
UIViewRoot view = super.restoreView(context, viewId);
if (getCsrfToken(context).equals(view.getAttributes().get(CSRF_TOKEN_KEY))) {
return view;
} else {
HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
if (session != null) {
session.invalidate(); //invalidate session so (my custom and unrelated) PhaseListener will notice that its a bad session now
}
try {
FacesContext.getCurrentInstance().getExternalContext().redirect("CSRF detected and blocked"); //better looking user feedback
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
旧解决方案
I tried without success so far,
添加到 faces-config.xml
<render-kit>
<renderer>
<component-family>javax.faces.Form</component-family>
<renderer-type>javax.faces.Form</renderer-type>
<renderer-class>com.communitake.mdportal.renderers.CTFormRenderer</renderer-class>
</renderer>
</render-kit>
Then in CTFormRenderer.java
@Override
public void encodeEnd(FacesContext context, UIComponent arg1) throws IOException {
//how to set form value be a CSRF token?
}
@Override
public void decode(FacesContext context, UIComponent component) {
HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
String token = (String) session.getAttribute(CSRFTOKEN_NAME);
String tokenFromForm = //how to get the value stored in form value attribute because (String) component.getAttributes().get("value"); return null
//check token against tokenFromForm...
}