Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jsf 2 通过客户端状态保存防止JSF2中的CSRF_Jsf 2_Csrf_Viewstate_Jsf 2.2_Myfaces - Fatal编程技术网

Jsf 2 通过客户端状态保存防止JSF2中的CSRF

Jsf 2 通过客户端状态保存防止JSF2中的CSRF,jsf-2,csrf,viewstate,jsf-2.2,myfaces,Jsf 2,Csrf,Viewstate,Jsf 2.2,Myfaces,我将MyFaces2.2.3与客户端状态保存+PrimeFaces一起使用 在询问我是谁之后,我可以通过覆盖from呈现程序来注入我自己的CSRF令牌,使该值成为CSRF令牌 我正在寻找一种根本不会强迫我修改xhtml页面的解决方案:) BalusC通过扩展ViewHandlerWrapper,提出了一种更好的防止CSRF攻击的方法,效果很好,我只需用以下方式修改restoreView public UIViewRoot restoreView(FacesContext context, St

我将MyFaces2.2.3与客户端状态保存+PrimeFaces一起使用

在询问我是谁之后,我可以通过覆盖from呈现程序来注入我自己的CSRF令牌,使该值成为CSRF令牌

我正在寻找一种根本不会强迫我修改xhtml页面的解决方案:)


BalusC通过扩展
ViewHandlerWrapper
,提出了一种更好的防止CSRF攻击的方法,效果很好,我只需用以下方式修改
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;
    }
}

旧解决方案

我试过了,但至今没有成功

添加到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>   

我不想在每个
h:form
中添加自定义组件,而是想扩展
表单
渲染器,使我的所有表单都具有
csrf令牌
这种
渲染器覆盖方法对PrimeFaces
partialSubmit=“true”
不安全。此外,重用标识提交表单的隐藏字段将是特定于JSF实现的,因为这不是JSF API的一部分

再想一想,直接在JSF视图状态本身中存储CSRF令牌要简单得多。您可以使用自定义的
ViewHandler
实现这一点,如下所示,它在
UIViewRoot
中设置一个属性(自动保存在JSF视图状态中):

请注意,当
restoreView()
返回
null
时,JSF将抛出一个
ViewExpiredException
“像往常一样”

要使其运行,请在
faces config.xml
中按如下方式注册:

<application>
    <view-handler>com.example.CsrfViewHandler</view-handler>    
</application>

在普通jsf中,它在没有PrimeFaces的情况下工作吗(只是为了确定)?如果没有,它是否与Mojarra一起工作?我不完全清楚您在这里的方向:“我可以通过覆盖从渲染器来注入我自己的CSRF令牌,使其值成为CSRF令牌”这是否意味着您要手动指定CSRF令牌?您知道它必须与服务器最初生成的内容相对应,对吗?@kolossus,您可以在我前面的问题和BalusC答案中了解我为什么需要此解决方案,您是否也计划生成此令牌?或者您想检索股票JSF值?我计划自己生成它谢谢!看起来正是我所需要的,明天将测试:)b.t.w在不等于的情况下重定向到某个自定义错误页面,而不是返回null并显示ViewExpiredException页面,可以吗?检查了它,尽管事实上
getCsrfToken(context).equals(view.getAttributes().get(CSRF_TOKEN_KEY))
为false并且restoreView中返回null,jsf仍然继续执行
f:ajax
操作
方法,extenral html仍然能够发布其数据,但是如果我替换
则返回null带有
FacesContext.getCurrentInstance().getExternalContext().redirect(“somePage.jsf”);return null
它将不会继续执行操作方法hm,应用程序中是否有更多的视图处理程序?不,它是唯一的一个,实际上,重定向充当了一个
流劫持
它实际上并不是重定向,因为外部表单提交返回一个xml,浏览器显示:
这个xml文件似乎没有任何与之相关的样式信息。文档树如下所示无法重现JSF仍然使用MyFaces2.2.8执行操作方法的情况。您使用哪些上下文参数设置?
public class CsrfViewHandler extends ViewHandlerWrapper {

    private static final String CSRF_TOKEN_KEY = CsrfViewHandler.class.getName();

    private ViewHandler wrapped;

    public CsrfViewHandler(ViewHandler wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public UIViewRoot restoreView(FacesContext context, String viewId) {
        UIViewRoot view = super.restoreView(context, viewId);
        return getCsrfToken(context).equals(view.getAttributes().get(CSRF_TOKEN_KEY)) ? view : null;
    }

    @Override
    public void renderView(FacesContext context, UIViewRoot view) throws IOException, FacesException {
        view.getAttributes().put(CSRF_TOKEN_KEY, getCsrfToken(context));
        super.renderView(context, view);
    }

    private String getCsrfToken(FacesContext context) {
        String csrfToken = (String) context.getExternalContext().getSessionMap().get(CSRF_TOKEN_KEY);

        if (csrfToken == null) {
            csrfToken = UUID.randomUUID().toString();
            context.getExternalContext().getSessionMap().put(CSRF_TOKEN_KEY, csrfToken);
        }

        return csrfToken;
    }

    @Override
    public ViewHandler getWrapped() {
        return wrapped;
    }

}
<application>
    <view-handler>com.example.CsrfViewHandler</view-handler>    
</application>
FacesContext context = FacesContext.getCurrentInstance();

if (!context.getApplication().getStateManager().isSavingStateInClient(context)) {
    throw new IllegalStateException("This view handler is only applicable when JSF is configured with "
        + StateManager.STATE_SAVING_METHOD_PARAM_NAME + "=" + StateManager.STATE_SAVING_METHOD_CLIENT);
}