在springmvc中基于拦截器实现敏感词过滤
将两个类SensitiveWordInit.java(实例化敏感词map类)和SensitivewordUtils.java(敏感词工具类)放入util中
package com.util; import com.entity.SysSensitivewords;//这里是敏感词实体类有对应的service dao从数据库查数据也可以用读txt文件来实现敏感词map的实例化 import java.util.*; /** * 敏感词库初始化 * * @author AlanLee */ public class SensitiveWordInit { /** * 敏感词库 */ public static HashMap sensitiveWordMap; /** * 初始化敏感词 * * @return */ public static Map initKeyWord(List<SysSensitivewords> sensitiveWords) { try { // 从敏感词集合对象中取出敏感词并封装到Set集合中 Set<String> keyWordSet = new HashSet<String>(); for (SysSensitivewords s : sensitiveWords) { keyWordSet.add(s.getContent().trim()); } // 将敏感词库加入到HashMap中 addSensitiveWordToHashMap(keyWordSet); } catch (Exception e) { e.printStackTrace(); } return sensitiveWordMap; } /** * 封装敏感词库 * * @param keyWordSet */ @SuppressWarnings("rawtypes") private static void addSensitiveWordToHashMap(Set<String> keyWordSet) { // 初始化HashMap对象并控制容器的大小 sensitiveWordMap = new HashMap(keyWordSet.size()); // 敏感词 String key = null; // 用来按照相应的格式保存敏感词库数据 Map nowMap = null; // 用来辅助构建敏感词库 Map<String, String> newWorMap = null; // 使用一个迭代器来循环敏感词集合 Iterator<String> iterator = keyWordSet.iterator(); while (iterator.hasNext()) { key = iterator.next(); // 等于敏感词库,HashMap对象在内存中占用的是同一个地址,所以此nowMap对象的变化,sensitiveWordMap对象也会跟着改变 nowMap = sensitiveWordMap; for (int i = 0; i < key.length(); i++) { // 截取敏感词当中的字,在敏感词库中字为HashMap对象的Key键值 char keyChar = key.charAt(i); // 判断这个字是否存在于敏感词库中 Object wordMap = nowMap.get(keyChar); if (wordMap != null) { nowMap = (Map) wordMap; } else { newWorMap = new HashMap<String, String>(); newWorMap.put("isEnd", "0"); nowMap.put(keyChar, newWorMap); nowMap = newWorMap; } // 如果该字是当前敏感词的最后一个字,则标识为结尾字 if (i == key.length() - 1) { nowMap.put("isEnd", "1"); } // System.out.println("封装敏感词库过程:"/*+sensitiveWordMap*/); } //System.out.println("查看敏感词库数据:" /*+ sensitiveWordMap*/); } System.out.println("查看敏感词库数据:" + sensitiveWordMap); } }
package com.util; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * 敏感词过滤工具类 * * @author AlanLee */ public class SensitivewordUtils { /** * 敏感词库 */ public static Map sensitiveWordMap = null; /** * 只过滤最小敏感词 */ public static int minMatchTYpe = 1; /** * 过滤所有敏感词 */ public static int maxMatchType = 2; /** * 敏感词库敏感词数量 * * @return */ public static int getWordSize() { if (SensitivewordUtils.sensitiveWordMap == null) { return 0; } return SensitivewordUtils.sensitiveWordMap.size(); } /** * 是否包含敏感词 * * @param txt * @param matchType * @return */ public static boolean isContaintSensitiveWord(String txt, int matchType) { boolean flag = false; for (int i = 0; i < txt.length(); i++) { int matchFlag = checkSensitiveWord(txt, i, matchType); if (matchFlag > 0) { flag = true; } } return flag; } /** * 获取敏感词内容 * * @param txt * @param matchType * @return 敏感词内容 */ public static Set<String> getSensitiveWord(String txt, int matchType) { Set<String> sensitiveWordList = new HashSet<String>(); for (int i = 0; i < txt.length(); i++) { int length = checkSensitiveWord(txt, i, matchType); if (length > 0) { // 将检测出的敏感词保存到集合中 sensitiveWordList.add(txt.substring(i, i + length)); i = i + length - 1; } } return sensitiveWordList; } /** * 替换敏感词 * * @param txt * @param matchType * @param replaceChar * @return */ public static String replaceSensitiveWord(String txt, int matchType, String replaceChar) { String resultTxt = txt; Set<String> set = getSensitiveWord(txt, matchType); Iterator<String> iterator = set.iterator(); String word = null; String replaceString = null; while (iterator.hasNext()) { word = iterator.next(); replaceString = getReplaceChars(replaceChar, word.length()); resultTxt = resultTxt.replaceAll(word, replaceString); } return resultTxt; } /** * 替换敏感词内容 * * @param replaceChar * @param length * @return */ private static String getReplaceChars(String replaceChar, int length) { String resultReplace = replaceChar; for (int i = 1; i < length; i++) { resultReplace += replaceChar; } return resultReplace; } /** * 检查敏感词数量 * * @param txt * @param beginIndex * @param matchType * @return */ public static int checkSensitiveWord(String txt, int beginIndex, int matchType) { boolean flag = false; // 记录敏感词数量 int matchFlag = 0; char word = 0; Map nowMap = SensitivewordUtils.sensitiveWordMap; for (int i = beginIndex; i < txt.length(); i++) { word = txt.charAt(i); // 判断该字是否存在于敏感词库中 nowMap = (Map) nowMap.get(word); if (nowMap != null) { matchFlag++; // 判断是否是敏感词的结尾字,如果是结尾字则判断是否继续检测 if ("1".equals(nowMap.get("isEnd"))) { flag = true; // 判断过滤类型,如果是小过滤则跳出循环,否则继续循环 if (SensitivewordUtils.minMatchTYpe == matchType) { break; } } } else { break; } } if (!flag) { matchFlag = 0; } return matchFlag; } }
实现拦截器
package com.interceptor; import org.apache.log4j.Logger; import org.springframework.beans.factory.BeanFactory; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.*; /** * 拦截敏感词 */ public class DFAInterceptor implements HandlerInterceptor { private static final Logger logger = Logger.getLogger(DFAInterceptor.class); @Resource SysSensitivewordsService sysSensitivewordsService; private List<String> excludeUrls; public List<String> getExcludeUrls() { return excludeUrls; } public void setExcludeUrls(List<String> excludeUrls) { this.excludeUrls = excludeUrls; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } /** * 之前拦截 * * @param request * @param httpServletResponse * @param o * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object o) throws Exception { String requestPath = this.getRequestPath(request);// 用户访问的资源地址 // 如果该请求不在拦截范围内,直接返回true if (excludeUrls.contains(requestPath)) { return true; } else { //遍历ParameterMap获取值 Map<String, String[]> parameterMap = request.getParameterMap(); StringBuffer sb = new StringBuffer(); Iterator<Map.Entry<String, String[]>> iterator = parameterMap.entrySet().iterator(); while (iterator.hasNext()) { String[] value = iterator.next().getValue(); sb.append(Arrays.toString(value)); } //存在实例化的敏感词map就不查数据库 if (SensitiveWordInit.sensitiveWordMap == null || SensitivewordUtils.getWordSize() == 0) { List<SysSensitivewords> bySearch = sysSensitivewordsService.findBySearch(new SysSensitivewords()); SensitivewordUtils.sensitiveWordMap = SensitiveWordInit.initKeyWord(bySearch); } //判断是否存在敏感词 存在抛出exist_sensitivewords异常与页面配置文件对应 boolean flag = SensitivewordUtils.isContaintSensitiveWord(sb.toString(), 1); if (flag) {//此处用的出现敏感词抛异常前端显示的方式 实际情况实际处理比如替换的时候就调用replaceSensitiveWord()方法 但是如果是替换 就不能直接遍历parametermap获取值拼接字符串
throw new GlobalException("exist_sensitivewords");} return !flag ; } } /** * 截取访问路径 * * @param request * @return */ public static String getRequestPath(HttpServletRequest request) { String requestPath = request.getRequestURI() ; // 去掉其他参数 if (requestPath.indexOf( "&") > - 1) { requestPath = requestPath.substring( 0 , requestPath.indexOf( "&")) ; } // 去掉jsessionid参数 if (requestPath.indexOf( ";") > - 1) { requestPath = requestPath.substring( 0 , requestPath.indexOf( ";")) ; } // 去掉项目路径 requestPath = requestPath.substring(request.getContextPath().length() + 1) ; return requestPath ; }}
spring-mvc.xml配置
<!-- 拦截器 --> <mvc:interceptors>
<mvc:interceptor><!--<mvc:mapping path="/**"/>这是拦截所有url--> < mvc :mapping path ="/**/save" /> <bean class ="com.idp.common.interceptor.DFAInterceptor" > <property name ="excludeUrls" > <list> <value>login/checkUser </value> <value>login/getMailVerifyCode </value> <value>login/logout </value> <value>user/updatePwd </value> </list> </property> </bean> </ mvc :interceptor> </ mvc :interceptors>
实体类就是很简单的
public class SysSensitivewords extends BaseEntity implements Serializable { private static final long serialVersionUID = 1L; /**id*/ private Integer id; /**类型*/ private String type; /**内容*/ private String content; /** *方法: 取得Integer *@return: Integer id */ public Integer getId(){ return this.id; } /** *方法: 设置Integer *@param: Integer id */ public void setId(Integer id){ this.id = id; } /** *方法: 取得String *@return: String 类型 */ public String getType(){ return this.type; } /** *方法: 设置String *@param: String 类型 */ public void setType(String type){ this.type = type; } /** *方法: 取得String *@return: String 内容 */ public String getContent(){ return this.content; } /** *方法: 设置String *@param: String 内容 */ public void setContent(String content){ this.content = content; } }