`

JSF应对Cross-Site Request Forgery (CSRF)攻击

    博客分类:
  • JSF
阅读更多

JSF 2.x has already builtin CSRF prevention in flavor of javax.faces.ViewState hidden field in the form when using server side state saving. In JSF 1.x this value was namely pretty weak and too easy predictable (it was actually never intended as CSRF prevention). In JSF 2.0 this has been improved by using a long and strong autogenerated value instead of a rather predictable sequence value and thus making it a robust CSRF prevention.

In JSF 2.2 this is even be further improved by making it a required part of the JSF specification, along with a configurable AES key to encrypt the client side state, in case client side state saving is enabled. New in JSF 2.2 is CSRF protection on GET requests by <protected-views>.

 

使用JSF 1.x的遗留代码,可以扩展form,在form内增加一个token,token通过SessionListener生成,保存在Session中,代码如下:

CsrfSessionListener

public class CsrfSessionListener implements HttpSessionListener {
    private static final String CSRF_TOKEN_NAME = "CsrfToken";

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        session.setAttribute(CSRF_TOKEN_NAME, UUID.randomUUID().toString());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {

    }
}

 CsrfForm

public class CsrfForm extends HtmlForm {

    private static final String CSRF_TOKEN_NAME = "CsrfToken";
    private static final String CSRF_TOKEN_ID = "csrf_token";

    @Override
    public void encodeEnd(FacesContext context) throws IOException {
        encodeCsrfTokenInput(context);
        super.encodeEnd(context);
    }

    private void encodeCsrfTokenInput(FacesContext context) throws IOException {
        ResponseWriter responseWriter = context.getResponseWriter();
        responseWriter.startElement("input", null);
        responseWriter.writeAttribute("type", "hidden", null);
        responseWriter.writeAttribute("id", getCsrfInputClientId(context), null);
        responseWriter.writeAttribute("name", CSRF_TOKEN_ID, null);
        responseWriter.writeAttribute("value", getToken(context), "value");
        responseWriter.endElement("input");
    }

    @Override
    public void decode(FacesContext context) {
        Map<String, String> requestMap = context.getExternalContext().getRequestParameterMap();
        String value = requestMap.get(CSRF_TOKEN_ID);

        // check if the token exists
        if (value == null || "null".equals(value) || "".equals(value)) {
            throw new CsrfException("CSRFToken is missing!");
        }

        String token = getToken(context);
        // check the values for equality
        if (!value.equalsIgnoreCase(token)) {
            throw new CsrfException("CSRFToken does not match!");
        }
        super.decode(context);
    }

    private String getCsrfInputClientId(FacesContext context) {
        return getClientId(context) + ":" + CSRF_TOKEN_ID;
    }

    private String getToken(FacesContext context) {
        HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
        return (String) session.getAttribute(CSRF_TOKEN_NAME);
    }

}

CsrfException

public class CsrfException extends RuntimeException {
    public CsrfException(String message) {
        super(message);
    }
}

然后在faces-config.xml中增加配置,使用CsrfForm:

<component>
  <component-type>javax.faces.HtmlForm</component-type>
  <component-class>org.iata.csrf.CsrfForm</component-class>
</component>

 

验证Referer

登录后将host保存在Session中

session.setAttribute("HOST", req.getHeader("host"));

然后在filter中验证:

package org.iata.csrf;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class CsrfFilter implements Filter {
    private static final String HTTP = "http://";
    private static final String HTTPS = "https://";
    private static final String REGEX = "https://|http://";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        HttpSession session = req.getSession(false);
        String host = (String) session.getAttribute("HOST");

        String referer = req.getHeader("Referer");
        if (referer == null) {
            chain.doFilter(request, response);
            return;
        }

        if (referer.startsWith(HTTP) || referer.startsWith(HTTPS)) {
            referer = referer.replaceFirst(REGEX, "");
        }
        if (referer.startsWith(host)) {
            chain.doFilter(request, response);
            return;
        }

        res.sendRedirect(req.getContextPath() + "/NoAuthorityError.seam");
    }

    @Override
    public void destroy() {

    }
}

 

CSRF 攻击的应对之道

CSRF的攻击与防御

Java EE 7: Implementing CSRF Protection with JSF 2.2

Preventing CSRF with JSF 2.0

Tomcat CSRF Prevention Filter

Seam Cross Site Request Forgery

分享到:
评论

相关推荐

    jsf-api-2.0.3.jar.zip_jsf api_jsf jar包_jsf-api-2.0.3.jar_jsf-api

    在部署包含JSF功能的Web应用到Tomcat时,确保所有必要的库,如`jsf-api.jar`(通常与`jsf-impl.jar`一起使用,提供JSF实现),被正确地添加到Tomcat的类路径(ClassPath)中是至关重要的。如果缺失这些库,应用程序...

    JSF-AV-rules.rar_JSF AV rule_JSF-AV_JSF-AV-rules_航空C++编程规范

    《JSF-AV-rules.rar》是一个压缩包文件,包含了航空C++编程规范,这个规范主要针对的是在航空系统开发中使用C++编程时应当遵循的一系列规则和标准。航空系统的软件开发对于安全性、可靠性和可维护性有着极高的要求,...

    jsf-api-2.0.jar

    这是jsf-api-2.0.jar,为了使用方便传上来.只是个jar包.

    jboss-ajax4jsf-1.1.1-src

    【标题】"jboss-ajax4jsf-1.1.1-src" 是一个开源项目,主要涉及Ajax4jsf框架的源代码版本,版本号为1.1.1。Ajax4jsf是针对JavaServer Faces (JSF) 技术的一个扩展,它允许开发者在JSF应用中无缝集成Ajax功能,提升...

    参考合同-集体林权流转合同(JSF-2015-2602).zip

    《集体林权流转合同》(JSF-2015-2602)是针对我国农村集体林地使用权和林木所有权转移的一种规范性法律文件。这份文档,以.docx格式存储在压缩包内,旨在为涉及集体林权交易的各方提供一个标准化的合同模板,确保...

    jsf-impl-2.0.0-src.jar

    jsf-impl-2.0.0源代码文件, jsf-impl-2.0.0-SNAPSHOT-sources.jar

    jsf-api-1.2

    综上所述,"jsf-api-1.2"提供了丰富的API和功能,使开发者能够高效地构建和维护企业级的Java Web应用程序。通过对组件、事件、Managed Beans、视图状态、转换验证、导航、国际化以及错误处理的理解和熟练运用,...

    jsf-impl-1.2_15.jar

    这是jsf-impl-1.2_15.jar,为了使用方便传上来.只是个jar包.

    jsf-spring-boot-starter-2.2.6.zip

    【标题】"jsf-spring-boot-starter-2.2.6.zip" 是一个基于Java Server Faces (JSF) 和Spring Boot的启动器项目,版本为2.2.6。这个压缩包通常包含了用于快速搭建JSF应用在Spring Boot环境中的必要组件和配置。 ...

    JSF-api-1.2_14-sources.jar

    JSF-api-1.2_14-sources.jar,提供了jsf使用时的多种内部类。

    一个简单的jsf例子------JSF2学习笔记1

    - `jsf-impl.jar` 和 `jsf-api.jar` 包含了JSF2的核心实现和API,供应用程序使用。 - `commons-collections-3.1.jar` 提供了集合操作的扩展,常常用于辅助处理数据。 - `commons-beanutils-1.8.0.jar` 提供了对...

    jsf-spring-4.0.3

    标题"jsf-spring-4.0.3"表明这是一个关于JSF与Spring整合的特定版本,4.0.3可能指的是Spring框架的一个版本,这通常意味着该资源包含了使得这两个框架能够协同工作的配置和示例代码。 在描述中提到的"jsf他spring...

    jsf-api-1.2-12.jar

    jsf-api-1.2-12.jar

    JavaEE源代码 jsf-api

    JavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-...

    jsf-spring-hibernate整合

    本项目"jsf-spring-hibernate整合"旨在将这三大技术进行无缝集成,采用基于注解的方式来简化配置,提高开发效率。 JSF(JavaServer Faces)是Java平台上的一个标准组件模型,用于构建富互联网应用程序(RIA)。它...

    JSF资源---精心收集,奉献给大家

    **JSF(JavaServer Faces)** 是Java平台上的一种开源Web应用程序框架,主要用于构建用户界面。它简化了前端和后端的交互,通过组件模型、事件处理和生命周期管理为开发人员提供了一种高效的方式去创建动态、数据...

    jsf-api,jsf-impl,jst1-1.2,javaee

    标题中的"jsf-api"和"jsf-impl"分别代表了JSF框架的API接口和其实现。"jsf-api" JAR文件包含了JSF框架的公共接口和类,定义了各种组件、事件和生命周期方法,供开发者在代码中引用。而"jsf-impl" JAR文件则提供了...

    JavaEE源代码 jsf-impl

    JavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源...

    jsf-by-example-源码.rar

    在这个名为"jsf-by-example-源码"的压缩包中,我们很可能会找到一系列关于JSF应用开发的示例代码。 **1. JSF框架概述** JSF遵循MVC(Model-View-Controller)设计模式,提供了一种声明式的方式来管理Web界面的生命...

Global site tag (gtag.js) - Google Analytics