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;
}
}