您的位置:首页 > 编程语言 > Java开发

Java实现非法关键词过滤

2018-03-01 16:08 267 查看
功能说明:
    对用户输入的参数进行过滤,并用*进行参数替换。

1.Filter(过滤器)的使用
    创建类KeyWordFilter(实现Filter),只需要实现其中的doFilter方法即可,在web.xml添加过滤器的配置。<filter>
<filter-name>keyWordFilter</filter-name>
<filter-class>com.uas.platform.b2c.core.filter.KeyWordFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>keyWordFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>    后续发现,过滤器不太好配置拦截的uri,如果想要对某一些url进行拦截,还是SpringMvc拦截器比较好。
2.参数中非法关键词处理@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException,
ServletException {
HttpServletRequest req = (HttpServletRequest) arg0;
HttpServletResponse response = (HttpServletResponse) arg1;
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
String contentType = req.getContentType();
String method = req.getMethod();
String uri = req.getRequestURI();
// POST请求 或 PUT请求,并且不是附件上传请求,并且不是hessian请求
if(("POST".equals(method) || "PUT".equals(method)) &&
(StringUtils.isEmpty(contentType) || !contentType.contains("multipart")) &&
!uri.contains(HESSIAN_URI_PREFIX)){
//注入Service
ServletContext sc = req.getSession().getServletContext();
XmlWebApplicationContext cxt = (XmlWebApplicationContext) WebApplicationContextUtils.getWebApplicationContext(sc);
KeyWordService keyWordService= null;
if(cxt != null && cxt.getBean("keyWordService") != null && keyWordService == null)
keyWordService = (KeyWordService) cxt.getBean("keyWordService");
if(keyworsSet == null){
keyworsSet = keyWordService.getAllKeyWordContent();
}
//request包装类 改写getParameterValues和getInputStream
ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(req);
arg2.doFilter(requestWrapper, response);
}else{
arg2.doFilter(req, response);
}
}
    a.改写request包装类BodyReaderHttpServletRequestWrapper,实现参数获取以及处理,注意:获取到了输入流之后,流自动被关闭,所以这里需要重新创建/**
* 用于将request重新进行封装
*
* @author liusw
*/
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;

public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));
}

@Override
public String[] getParameterValues(String name) {
String[] result = super.getParameterValues(name);
if(result!=null &&result.length>0){
Set<String> keywords = null;
for(int i=0;i<result.length;i++){
if(KeyWordFilter.keyworsSet!=null){
keywords = KeyWordFilterUtil.getSensitiveWord(result[i], 0,KeyWordFilterUtil.initKeyWord(
KeyWordFilter.keyworsSet));
if(keywords!=null && keywords.size()>0){
for(String s : keywords){
result[i] = result[i].replaceAll(s,"*");
}
}
}
}
}
return result;
}

@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}

@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
};
}

@Override
public String getHeader(String name) {
return super.getHeader(name);
}

@Override
public Enumeration<String> getHeaderNames() {
return super.getHeaderNames();
}

@Override
public Enumeration<String> getHeaders(String name) {
return super.getHeaders(name);
}
}    b.使用敏感词DFA算法实现快速判断参数中的非法关键词public class KeyWordFilterUtil {
public static int minMatchTYpe = 1; //最小匹配规则
public static int maxMatchType = 2; //最大匹配规则

public static Set<String> getSensitiveWord(String txt , int matchType,Map nowMap) {
Set<String> sensitiveWordList = new HashSet<String>();

for (int i = 0; i < txt.length(); i++) {
int length = CheckSensitiveWord(txt,i, matchType,nowMap); //判断是否包含敏感字符
if (length > 0) { //存在,加入list中
sensitiveWordList.add(txt.substring(i, i + length));
i = i + length - 1; //减1的原因,是因为for会自增
}
}
return sensitiveWordList;
}
/**
* 检查文字中是否包含敏感字符
*/
public static int CheckSensitiveWord(String txt,int beginIndex,int matchType,Map nowMap){
boolean flag = false; //敏感词结束标识位:用于敏感词只有1位的情况
int matchFlag = 0; //匹配标识数默认为0
char word = 0;
for(int i = beginIndex; i < txt.length() ; i++){
word = txt.charAt(i);
nowMap = (Map) nowMap.get(word); //获取指定key
if(nowMap != null){ //存在,则判断是否为最后一个
matchFlag++; //找到相应key,匹配标识+1
if("1".equals(nowMap.get("isEnd"))){ //如果为最后一个匹配规则,结束循环,返回匹配标识数
flag = true; //结束标志位为true
if(KeyWordFilterUtil.minMatchTYpe == matchType){ //最小规则,直接返回,最大规则还需继续查找
break;
}
}
}
else{ //不存在,直接返回
break;
}
}
if(matchFlag < 2 || !flag){ //长度必须大于等于1,为词
matchFlag = 0;
}
return matchFlag;
}

/**
* 初始化敏感词
* @param keyWordSet
* @return
*/
public static Map initKeyWord(Set<String> keyWordSet){
HashMap sensitiveWordMap = null;
try {
sensitiveWordMap = new HashMap(keyWordSet.size()); //初始化敏感词容器,减少扩容操作
String key = null;
Map nowMap = null;
Map<String, String> newWorMap = null;
//迭代keyWordSet
Iterator<String> iterator = keyWordSet.iterator();
while(iterator.hasNext()){
key = iterator.next(); //关键字
nowMap = sensitiveWordMap;
for(int i = 0 ; i < key.length() ; i++){
char keyChar = key.charAt(i); //转换成char型
Object wordMap = nowMap.get(keyChar); //获取

if(wordMap != null){ //如果存在该key,直接赋值
nowMap = (Map) wordMap;
}
else{ //不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个
newWorMap = new HashMap<String,String>();
newWorMap.put("isEnd", "0"); //不是最后一个
nowMap.put(keyChar, newWorMap);
nowMap = newWorMap;
}

if(i == key.length() - 1){
nowMap.put("isEnd", "1"); //最后一个
}
}
}
//spring获取application,然后application.setAttribute("sensitiveWordMap",sensitiveWordMap);
} catch (Exception e) {
e.printStackTrace();
}
return sensitiveWordMap;
}
}3.传递给控制层

    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息