防止CSRF攻击

攻击通过在授权用户访问的页面中包含链接或者脚本的方式工作。例

 如:一个网站用户Bob可能正在浏览聊天论坛,而同时另一个用户Alice也在此论坛中,并且后者刚刚发布了一个具有Bob银行链接的图片消息。设想一下,Alice编写了一个在Bob的银行站点上进行取款的form提交的链接,并将此链接作为图片src。如果Bob的银行在cookie中保存他的授权信息,并且此cookie没有过期,那么当Bob的浏览器尝试装载图片时将提交这个取款form和他的cookie,这样在没经Bob同意的情况下便授权了这次事务。

CSRF是一种依赖web浏览器的、被混淆过的代理人攻击(deputy attack)。在上面银行示例中的代理人是Bob的web浏览器,它被混淆后误将Bob的授权直接交给了Alice使用。

通过实现Filter过滤器对每一次请求进行验证,验证方式是:验证请求的Referer是否有效
 

package com.skysz.framework.filter.csrf;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.UUID;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import com.skysz.framework.logger.SkyszLogger;
import com.skysz.framework.logger.SkyszLoggerF;
import com.skysz.framework.utils.StringUtils;

public class CSRFFilter implements Filter {

	private static SkyszLogger log = SkyszLoggerF.getLog(CSRFFilter.class);

	private static String IPAUTHFILTER = "";// 请求IP地址白名单
	private static String CSRFFILTEREPARM = "";// 请求URL白名单

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		IPAUTHFILTER = filterConfig.getInitParameter("ipAuthFilter");
		CSRFFILTEREPARM = filterConfig.getInitParameter("csrfFiltereParm");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		// 从 HTTP 头中取得 Referer 值
		String referer = req.getHeader("Referer");
		String reqUrl = req.getRequestURL().toString();

		String whiteIpAll = IPAUTHFILTER;
		String[] whiteParams = CSRFFILTEREPARM.split(","); // 可以直接放行的路径,不用校验referer

		if (StringUtils.isNullOrBlank(whiteIpAll)) {
			log.error("CSRFFilter:The header is null ...");
			PrintWriter writer = response.getWriter();
			writer.println("The header is null");
			writer.close();
			return;
		}
		String[] whiteIPs = whiteIpAll.split(","); //
		boolean isgo = false; // 是否可以放行的标志

		// 如果referer为null的处理(ie windows.open() referer是为null的)
		if (StringUtils.isNullOrBlank(referer)) {
			// 匹配是否是合法请求(刚进入登录页面 referer为null)
			for (String whiteIP : whiteIPs) {
				if (reqUrl.equals(whiteIP)) {
					log.info("referer为null,请求路径:" + reqUrl + "和配置的" + whiteIP + "相等,此请求为合法请求,登录页面放行!");
					isgo = true;
					break;
				}
			}

			// 如果isgo已经为true则放行,后面的验证不在执行
			if (!isgo) {
				// 如果referer为null则用请求的url和可以放行的路径比对
				for (String whiteParam : whiteParams) {
					if (reqUrl.contains(whiteParam)) {
						log.info("referer为null,请求路径:" + reqUrl + "包含" + whiteParam + ",此请求为合法请求,放行!");
						isgo = true;
						break;
					}
				}
			}

		} else { // 如果referer不为null的处理
			for (int i = 0; i < whiteIPs.length; i++) {
				if (referer.trim().contains(whiteIPs[i])) {
					// log.info("referer的值为:" + referer + "包含" + whiteIPs[i] + ",此请求为合法请求,放行!");
					isgo = true;
					break;
				}
			}
		}

		if (!isgo) {
			log.error("referer的值为:" + referer + ",请求路径为:" + reqUrl + ",IP白名单:" + IPAUTHFILTER + ",参数url白名单:" + CSRFFILTEREPARM + ",不合法请求,拦截!");
			PrintWriter writer = response.getWriter();
			writer.println("The request you sent was exceptionally malicious " + referer + " contains :" + isgo + "(CSRF)");
			writer.close();
			return;
		}
		chain.doFilter(request, response);
	}

	public String generate() {
		return UUID.randomUUID().toString();
	}

	@Override
	public void destroy() {

	}

}
//在web.xml加上这个过滤器

   <filter>
		<filter-name>CSRFFilter</filter-name>
		<filter-class>com.text.framework.filter.csrf.CSRFFilter</filter-class>
		
		<init-param>
			<param-name>ipAuthFilter</param-name>
			<param-value>http://localhost:8015/</param-value> 
		</init-param>
		<init-param>
			<param-name>csrfFiltereParm</param-name>
			<param-value>index.html,index.jsp,app/authAction/loadAuthTopMenus.html,/app/hx/dzhd/accountReceipt_showReceipt.jsp,/app/hx/authCsrf/,/app/payFileAction/uploadAccsTemp.html/,/views/file/,/app/attachmentAction/uploadAccs.html</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CSRFFilter</filter-name>
		<url-pattern>*.html</url-pattern>
	</filter-mapping>

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值