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() { } }
相关推荐
在部署包含JSF功能的Web应用到Tomcat时,确保所有必要的库,如`jsf-api.jar`(通常与`jsf-impl.jar`一起使用,提供JSF实现),被正确地添加到Tomcat的类路径(ClassPath)中是至关重要的。如果缺失这些库,应用程序...
《JSF-AV-rules.rar》是一个压缩包文件,包含了航空C++编程规范,这个规范主要针对的是在航空系统开发中使用C++编程时应当遵循的一系列规则和标准。航空系统的软件开发对于安全性、可靠性和可维护性有着极高的要求,...
这是jsf-api-2.0.jar,为了使用方便传上来.只是个jar包.
【标题】"jboss-ajax4jsf-1.1.1-src" 是一个开源项目,主要涉及Ajax4jsf框架的源代码版本,版本号为1.1.1。Ajax4jsf是针对JavaServer Faces (JSF) 技术的一个扩展,它允许开发者在JSF应用中无缝集成Ajax功能,提升...
《集体林权流转合同》(JSF-2015-2602)是针对我国农村集体林地使用权和林木所有权转移的一种规范性法律文件。这份文档,以.docx格式存储在压缩包内,旨在为涉及集体林权交易的各方提供一个标准化的合同模板,确保...
jsf-impl-2.0.0源代码文件, jsf-impl-2.0.0-SNAPSHOT-sources.jar
综上所述,"jsf-api-1.2"提供了丰富的API和功能,使开发者能够高效地构建和维护企业级的Java Web应用程序。通过对组件、事件、Managed Beans、视图状态、转换验证、导航、国际化以及错误处理的理解和熟练运用,...
这是jsf-impl-1.2_15.jar,为了使用方便传上来.只是个jar包.
【标题】"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使用时的多种内部类。
- `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可能指的是Spring框架的一个版本,这通常意味着该资源包含了使得这两个框架能够协同工作的配置和示例代码。 在描述中提到的"jsf他spring...
jsf-api-1.2-12.jar
《江苏省商品交易市场设施租赁、管理服务合同》(JSF-2008-0601)是一份规范江苏省内商品交易市场设施租赁及管理服务的法律文件,旨在明确出租方(甲方)与承租方(乙方)之间的权利与义务。这份合同详细规定了租赁...
JavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-...
本项目"jsf-spring-hibernate整合"旨在将这三大技术进行无缝集成,采用基于注解的方式来简化配置,提高开发效率。 JSF(JavaServer Faces)是Java平台上的一个标准组件模型,用于构建富互联网应用程序(RIA)。它...
**JSF(JavaServer Faces)** 是Java平台上的一种开源Web应用程序框架,主要用于构建用户界面。它简化了前端和后端的交互,通过组件模型、事件处理和生命周期管理为开发人员提供了一种高效的方式去创建动态、数据...
标题中的"jsf-api"和"jsf-impl"分别代表了JSF框架的API接口和其实现。"jsf-api" JAR文件包含了JSF框架的公共接口和类,定义了各种组件、事件和生命周期方法,供开发者在代码中引用。而"jsf-impl" JAR文件则提供了...
JavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源...