跨站请求伪造CSRF(防御实例)

 

 

package com.wy.controller.console;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
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.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


import com.wy.domain.tool.CommonUtils;


/**
 * @desc CSRF防御跨站点伪造
 * 
 * @author hanfeng
 */

public class CsrfFilter implements Filter {


public static final String SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE = "springMacroRequestContext";

@SuppressWarnings("unused")
private int cookieMaxAge;

public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException {

HttpServletRequest httpReq = (HttpServletRequest) request;
HttpServletResponse httpResp = (HttpServletResponse) response;


HttpSession session = httpReq.getSession();

// 从 HTTP 头中取得 Referer 值
String referer = httpReq.getHeader( "Referer" ) ;

// 从 session 中得到 csrftoken 属性
String sToken = (String) session.getAttribute( "csrftoken" );


Cookie cookie = new Cookie( "csrftoken", sToken );

httpResp.addCookie(cookie);

//从Cookie里获取上次存入的refer信息
String refererTwo = cookie.getValue();

//判断是否为手机端访问
if( containsUrl( httpReq.getRequestURI() ) ){

chain.doFilter( request, response );

return;
}

if( sToken == null ) {
// 产生新的 token 放入 session 中
sToken = getUUID();

session.setAttribute( "csrftoken", sToken );

chain.doFilter( request, response );

 

 

} else if (sToken != null || ( referer != null || ( refererTwo != null ) ) && ( referer.trim().startsWith( CommonUtils.getRefererUrl() )  || refererTwo.trim().startsWith( CommonUtils.getRefererUrl() ) ) ) {

// 判断 Referer 是否以****** 开头 以及 sToken不为空


// 从请求参数中取得 csrftoken

String pToken = getRequestParams( httpReq, "csrftoken" );

String headerCsrfToken = cookie.getValue();

if ( sToken != null && pToken != null && ( sToken.equals( pToken ) || sToken.equals( headerCsrfToken ) ) ) {

chain.doFilter( request, response );

}else{

httpResp.sendRedirect( httpReq.getContextPath()+"/error.jsp" );

}
} else {

httpResp.sendRedirect( httpReq.getContextPath()+"/error.jsp" );

}

}

/**
* @desc 从request中获取参数

* @param request
* @param parameterName
* @author hanfeng
* @return
*/

@SuppressWarnings("unchecked")
private String getRequestParams( HttpServletRequest request, String parameterName ) {

Enumeration enums = request.getParameterNames();

String val = "";

while( enums.hasMoreElements() ){

String key = (String)enums.nextElement();

if( parameterName.equals( key ) ){

val = request.getParameter( key );
break;

}

}

return val;

}

/**
* @desc 自动生成UUID

* @author hanfeng
* @return
*/

public static String getUUID() {

UUID uuid = UUID.randomUUID();

String str = uuid.toString();

// 去掉"-"符号
String temp = str.substring( 0, 8 ) + str.substring( 9, 13 ) + str.substring( 14, 18 ) + str.substring( 19, 23 ) + str.substring( 24 );

return temp;

}


/**
* @desc Cookies信息超时

* @author hanfeng
*/

public void init(FilterConfig config) throws ServletException {


String cookieMaxAgeStr = config.getInitParameter("cookieMaxAge");

        if (cookieMaxAgeStr != null) {
       
            try {
           
                cookieMaxAge = Integer.parseInt(cookieMaxAgeStr);
                
            } catch (NumberFormatException nfe) {
           
                throw new ServletException("cookieMaxAge must be an integer: " + cookieMaxAgeStr, nfe);
                
            }
            
        } else {
       
            cookieMaxAge = 600; // 60*10 seconds = 10 min
            
        }

}


@Override
public void destroy() {

}


public static boolean containsUrl(String url) {

boolean ret = false;
/*不需要禁止访问的项目内方法*/
String[] array = new String[] {
"pAdwordCircleController", "pNewsController", 
"pInfoDisclosuresController", "pRegistController",
"pLoginController", "pMobileMessageController",
"pUserInfoController", "pQueryInfoController",
"pObjectionController", "pSuggestionsController",
"pInfoPolicyController", "pUpdateController",
"pReportController", "pMemberCostController"
};

ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(array));

for (int i = 0; i < arrayList.size(); i++) {

if( url.contains(arrayList.get(i).toString()) ){

ret = true;

break;
}

        }

return ret;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT_LOSER

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值