在项目中常常需要顾虑请求参数中的特殊字符,比如+,<,>等
解决方案是可以使用spring mvc 的拦截器,配合aspectJ使用
package com.cpic.core.web;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.jfree.util.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.cpic.caf.compon.business.common.entity.CodeEntryEO;
import com.cpic.caf.compon.tech.utils.JsonUtils;
import com.cpic.caf.compon.tech.utils.StringUtils;
import com.cpic.caf.pub.app.context.SpringAppContextUtil;
import com.cpic.caf.pub.security.context.SecurityContext;
import com.cpic.core.cache.DataCacheManager;
import com.cpic.core.filter.FilterUtils;
import com.cpic.core.httpHandler.entity.Response;
import com.cpic.cxyb.entity.LogManager;
import com.cpic.cxyb.entity.RybAuditLog;
import com.cpic.cxyb.service.LogManagerService;
import com.cpic.cxyb.service.RybAuditLogService;
import com.cpic.cxyb.threads.RybAuditLogSyncToDBThread;
import com.cpic.framework.entity.ResponseContent;
import com.cpic.xybx.security.MyUserInfoImpl;
import com.cpic.xybx.tools.CpicmIPUtil;
public class FilterTextSpecialString {
public static final Logger logger = LoggerFactory.getLogger ( FilterTextSpecialString.class );
DataCacheManager dataCacheManager;
LogManagerService logManagerService;
@Autowired
RybAuditLogService rybAuditLogService;
public static final String[] APP_METHOD = {"innerServerController.submit,innerServerController.submitContent"};
public static final String RETURN_TYPE_AJAX = "ResponseContent";
public static final String RETURN_TYPE_MV = "ModelAndView";
public static final String RETURN_TYPE_MAP = "Map";
public static final String RETURN_TYPE_VOID = "void";
public static final String RETURN_TYPE_STRING = "String";
//特殊字符的判断
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
this.dataCacheManager = (DataCacheManager)SpringAppContextUtil.getBean("dataCacheManager");
this.logManagerService = (LogManagerService)SpringAppContextUtil.getBean("logManagerService");
//从数据库获取文本框特殊字符过滤信息
CodeEntryEO codeEntry = null;
String speCharactor = "";
String method = pjp.getTarget().getClass().getName() + "." + pjp.getSignature().getName();
//获取映射方法
try{
String returnType = pjp.getSignature().toString().split(" ")[0];
if(StringUtils.isNotBlank(returnType) && RETURN_TYPE_MV.equals(returnType)){
Method targetMethod = ((MethodSignature)(pjp.getSignature())).getMethod();
Class> classtest = targetMethod.getDeclaringClass();
String classAnnotationValue = "";
String methodAnnotationValue = "";
Annotation[] classAnnotation = classtest.getAnnotations();
for (int i = 0; i < classAnnotation.length; i++) {
if(classAnnotation[i] instanceof RequestMapping){
RequestMapping requestmap = (RequestMapping) classAnnotation[i];
if(requestmap.value()[0] != null){
classAnnotationValue = (requestmap.value())[0];
}
break;
}
}
if(StringUtils.isNotBlank(classAnnotationValue)){
Annotation[] methodAnnotation = targetMethod.getAnnotations();
for (int i = 0; i < methodAnnotation.length; i++) {
if(methodAnnotation[i] instanceof RequestMapping){
RequestMapping requestmap = (RequestMapping) methodAnnotation[i];
if(requestmap.value()[0] != null){
methodAnnotationValue = (requestmap.value())[0];
}
break;
}
}
String catalog = classAnnotationValue+"/"+methodAnnotationValue;
//增加审计日志
if(RybAuditLogSyncToDBThread.menuMap.get(catalog) != null){
MyUserInfoImpl user = (MyUserInfoImpl) SecurityContext.getCurrentUser();
//UserDefault user = (UserDefault)servletRequest.getAttribute("user");
RybAuditLog auditLog = new RybAuditLog();
auditLog.setDatetime(new Date());
auditLog.setInterfacecode(catalog);
auditLog.setKind("web");
String requestName = (String) RybAuditLogSyncToDBThread.menuMap.get(catalog);
if(StringUtils.isNotBlank(requestName))auditLog.setInterfacename(requestName);
if(user != null){
String usertype = user.getUserType();
auditLog.setUnitcode(user.getOrgCode());
auditLog.setUsercode(user.getUserCode());
auditLog.setUsername(user.getUsername());
auditLog.setUsertype(usertype);
auditLog.setOrgid(user.getOrgId());
if(StringUtils.isNotBlank(usertype) && "CPICUser".equals(user.getUserType())){
auditLog.setUnitname((String)(RybAuditLogSyncToDBThread.orgMap).get(user.getOrgCode()));
}else{
auditLog.setUnitname((String)(RybAuditLogSyncToDBThread.outsideOrgMap).get(user.getOrgCode()));
}
}
this.rybAuditLogService.log(auditLog);
}
}
}
}catch(Exception e){
Log.error("记录审计日志出错"+e.getMessage());
}
boolean appFlag = false;
//判断是否是app
for(int i = 0 ; i < APP_METHOD.length ; i++){
if(method.indexOf(APP_METHOD[i]) >= 0){
appFlag = true;
break;
}
}
//文本过滤器不过滤类和方法,配置在数据库中为:类名.方法名,类名.方法名
CodeEntryEO codeEntryEO = dataCacheManager.getCodeEntryCacheByName("FilterConfig","TextSpecialCharactersException");
String exception = "";
if(codeEntryEO != null){
exception = codeEntryEO.getName();
}
String[] exceptions = exception.split(",");
boolean exec = true;
for(int i = 0 ; i < exceptions.length ; i ++){
if(method.indexOf(exceptions[i]) >= 0){
exec = false;
break;
}
}
boolean flag = false;//默认为假,有可能该Ctrl为例外或者没有参数则不作校验
if(exec){
if(appFlag ){
codeEntry = dataCacheManager.getCodeEntryCacheByName("FilterConfig","appTextSpecialCharacters");
}else{
codeEntry = dataCacheManager.getCodeEntryCacheByName("FilterConfig","TextSpecialCharacters");
}
if (codeEntry != null){
speCharactor = codeEntry.getName();
}
String[] list = {};
//如果过滤规则为空,则不过滤
if(StringUtils.isNotEmpty(speCharactor)){
//特殊字符串数组
list = speCharactor.split(",");
}
if(list.length > 0 && pjp.getArgs() != null && pjp.getArgs().length > 0){
for (int i = 0; i < pjp.getArgs().length; i++) {
if(pjp.getArgs()[i] instanceof LinkedHashMap){
Map map = (Map)pjp.getArgs()[i];
flag = typeJudge(map,list,method);
}else if(pjp.getArgs()[i] instanceof HttpServletRequest){
HttpServletRequest req = ((HttpServletRequest)pjp.getArgs()[i]);
Enumeration enu = req.getParameterNames();
while(enu.hasMoreElements()){
String paraName=(String)enu.nextElement();
if(req.getParameter(paraName) != null){
flag = FilterUtils.checkTextStringValue(req.getParameter(paraName).toUpperCase(),list);
}
//包含特殊字符退出循环
if(flag){
logger.info(method + "参数名为:"+paraName+" 的值为:"+req.getParameter(paraName)+" 中包含特殊字符。");
break;
}
}
}else if(pjp.getArgs()[i] instanceof String){
flag = FilterUtils.checkTextStringValue(pjp.getArgs()[i].toString().toUpperCase(),list);
}
//包含特殊字符退出循环,不校验下一个参数
if(flag){
break;
}
}
}
}
//没有特殊字符校验通过,调用ctrl方法执行业务
Object retVal = null;
if(!flag){
try{
retVal = pjp.proceed();
}catch(Exception e){
StackTraceElement stackTraceElement= e.getStackTrace()[e.getStackTrace().length-1];
stackTraceElement.getLineNumber();
logger.error ( "\n=========执行{}方法的{}行异常信息为:=========={}",method,stackTraceElement.getLineNumber(),e.fillInStackTrace ( ).toString ( ) );
//记录错误日志到数据库
LogManager logManager = new LogManager();
logManager.setErrormsg("执行" + method + "方法的" + stackTraceElement.getLineNumber() + "行发生错误:" + e.fillInStackTrace ( ).toString ( ));
logManager.setIp(CpicmIPUtil.getServerIp());
logManager.setCreattime(new Date());
String requestStr = getRequestStr(pjp);
logManager.setRequestmsg(requestStr);
logManager.setResponsemsg("系统异常:请联系系统管理员");
this.logManagerService.log(logManager);
//针对异常的处理
if(appFlag ){
Response response = new Response();
response.setStatus(Response.STATUS_ERROR);
response.setErrorCode(Response.ERROR_CODE_SYSTEM);
response.setErrorMessage("系统异常:请联系系统管理员");
retVal = response;
}else{
String returnType = pjp.getSignature().toString().split(" ")[0];
if(RETURN_TYPE_AJAX.equals(returnType)){
ResponseContent responseContent = new ResponseContent();
responseContent.setResultState(false);
responseContent.setErrorCode("-88888");
responseContent.setMsg("系统异常:请联系系统管理员");
retVal = responseContent;
}else if(RETURN_TYPE_MV.equals(returnType)){
//返回管理后台错误页面
ModelAndView mv = new ModelAndView("systemError");
mv.addObject("msg", "系统异常:请联系系统管理员");
retVal = mv;
}else if(RETURN_TYPE_STRING.equals(returnType)){
//返回管理后台错误页面
retVal = "systemError";
}else if(returnType.indexOf(RETURN_TYPE_MAP) >= 0){
Map responseContent = new HashMap();
responseContent.put("resultState",false);
responseContent.put("errorCode","-88888");
responseContent.put("msg","系统异常:请联系系统管理员");
retVal = responseContent;
}else if(returnType.indexOf(RETURN_TYPE_VOID) >= 0){
//void目前不作处理,如果扫描出问题,则在进行处理,把HttpServletResponse获得到,直接向页面输出以下字符串
// Map responseContent = new HashMap();
// responseContent.put("resultState",false);
// responseContent.put("errorCode","-88888");
// responseContent.put("msg","系统异常:请联系系统管理员");
// retVal = responseContent;
}
}
}
}else{//包含特殊字符
LogManager logManager = new LogManager();
logManager.setErrormsg("请求异常:请求参数不合法或请求参数被篡改");
logManager.setIp(CpicmIPUtil.getServerIp());
logManager.setCreattime(new Date());
String requestStr = getRequestStr(pjp);
logManager.setRequestmsg(requestStr);
logManager.setResponsemsg("请求异常:请求参数不合法或请求参数被篡改");
this.logManagerService.log(logManager);
if(appFlag ){
Response response = new Response();
response.setStatus(Response.STATUS_ERROR);
response.setErrorCode(Response.ERROR_CODE_SPECIAL_TEXT);
response.setErrorMessage("请求异常:请求参数不合法或请求参数被篡改");
retVal = response;
}else{
String returnType = pjp.getSignature().toString().split(" ")[0];
if(returnType.indexOf(RETURN_TYPE_AJAX) >= 0){
ResponseContent responseContent = new ResponseContent();
responseContent.setResultState(false);
responseContent.setErrorCode("-88888");
responseContent.setMsg("请求异常:请求参数不合法或请求参数被篡改");
retVal = responseContent;
}else if(returnType.indexOf(RETURN_TYPE_MV) >= 0){
//返回管理后台错误页面
ModelAndView mv = new ModelAndView("permissionError");
mv.addObject("msg", "请求异常:请求参数不合法或请求参数被篡改");
retVal = mv;
}else if(RETURN_TYPE_STRING.equals(returnType)){
//返回管理后台错误页面
retVal = "permissionError";
}else if(returnType.indexOf(RETURN_TYPE_MAP) >= 0){
Map responseContent = new HashMap();
responseContent.put("resultState",false);
responseContent.put("errorCode","-88888");
responseContent.put("msg","请求异常:请求参数不合法或请求参数被篡改");
retVal = responseContent;
}else if(returnType.indexOf(RETURN_TYPE_VOID) >= 0){
//void目前不作处理,如果扫描出问题,则在进行处理,把HttpServletResponse获得到,直接向页面输出以下字符串
// Map responseContent = new HashMap();
// responseContent.put("resultState",false);
// responseContent.put("errorCode","-88888");
// responseContent.put("msg","请求异常:请求参数不合法或请求参数被篡改");
// retVal = responseContent;
}
}
}
return retVal;
}
public static boolean checkTextStringValue(String str,String[] list){
boolean flag = true;
if(str!=null&&!"".equals(str)){
for(int i=0;i-1){
flag = false;
break;
}
}
}
return flag;
}
/**
* 类型判断
* @param map
* @return
*/
public boolean typeJudge(Map map,String[] list,String method) {
boolean flag = false;
for (String key : map.keySet()) {
try{
if(map.get(key) instanceof Integer){
continue;
}else if(map.get(key) instanceof Long){
continue;
}else if(map.get(key) instanceof String){
flag = FilterUtils.checkTextStringValue(map.get(key).toString().toUpperCase(),list);
if(flag){
logger.info(method + "|参数名为:"+key+" 的值为:"+map.get(key).toString()+" 中包含特殊字符。");
break;
}
}else if(map.get(key) instanceof Date){
continue;
}else if(map.get(key) instanceof BigDecimal){
continue;
}else if(map.get(key) instanceof List){//类型为list
continue;
}else if(map.get(key) instanceof Map){//类型为map
try{
if(map.get(key) != null && !"".equals ( map.get(key) )){
flag = typeJudge((Map)map.get(key),list,method);
if(flag){
logger.info(method + "|参数名为:"+key+" 的值为:"+map.get(key).toString()+" 中包含特殊字符。");
break;
}
}
}catch (Exception e) {
logger.error ( "\n=========异常信息为:==========\n{}",e.fillInStackTrace ( ).toString ( ) );
}
}
}catch(Exception e){
logger.error ( "\n=========异常信息为:==========\n{}",e.fillInStackTrace ( ).toString ( ) );
}
}
return flag;
}
private String getRequestStr(ProceedingJoinPoint pjp){
String requestStr = "";
if(pjp.getArgs() != null && pjp.getArgs().length > 0){
for (int i = 0; i < pjp.getArgs().length; i++) {
if(pjp.getArgs()[i] instanceof LinkedHashMap){
Map map = (Map)pjp.getArgs()[i];
requestStr += "Map参数值为:" + JsonUtils.objToJson(map) + "|";
}else if(pjp.getArgs()[i] instanceof HttpServletRequest){
HttpServletRequest req = ((HttpServletRequest)pjp.getArgs()[i]);
Enumeration enu = req.getParameterNames();
requestStr += "HttpServletRequest参数值为:" + JsonUtils.objToJson(enu) + "|";
}else if(pjp.getArgs()[i] instanceof String){
requestStr += "HttpServletRequest参数值为:" + pjp.getArgs()[i].toString() + "|";
}
}
}
return requestStr;
}
}