java過(guò)濾敏感詞實(shí)現(xiàn)字符串替換功能
很多網(wǎng)站都需要對(duì)于某些關(guān)鍵字或者某些敏感詞匯進(jìn)行過(guò)濾替換的功能。比如在輸入框中輸入些js 腳本,或者輸入些政府類型的詞匯等都是不允許的,但是你不能限制用戶的自由。所以對(duì)于網(wǎng)站的過(guò)濾功能就顯得很有必要了。對(duì)于一般的網(wǎng)站使用來(lái)說(shuō),不需要非常復(fù)雜的過(guò)濾算法等比較高端的實(shí)現(xiàn)。簡(jiǎn)單的用 filter 和 HttpServletRequestWrapper 就可以實(shí)現(xiàn)。
HttpServletRequestWrapper 的實(shí)現(xiàn)采用了包裝模式,具體介紹請(qǐng)另找資料。直接切入正題。實(shí)現(xiàn)思路:首先定義一個(gè) properties文件,在文件中存放需要替換的文字和替換后的文字,比如替換 fuck=** ,政府 =** ,替換 <=< 和 >=> (這樣就可以避免文本輸入的 js 腳本)。然后定義一個(gè)類來(lái)繼承 HttpServletRequestWrapper 達(dá)到包裝 request對(duì)象的作用,最后用一個(gè) filter 使用包裝后的 request 對(duì)象(即已經(jīng)經(jīng)過(guò)了過(guò)濾作用)。
keyword.properties文件:
CNM=**?? fuck=**?? <=<?? >=>
然后寫一個(gè)操作properties文件的工具類,PropertiesUtil.java
package?com.lhwl.elt.filter;
import?java.io.File;
import?java.io.FileInputStream;
import?java.io.InputStream;
import?java.util.Enumeration;
import?java.util.HashMap;
import?java.util.Iterator;
import?java.util.Map;
import?java.util.Properties;
import?java.util.Set;
public?class?PropertiesUtil{
public?static?Map?readProperties(String?src)?{
Properties?props?=?new?Properties();
Map?map?=?new?HashMap();
try?{
File?file=new?File(src);
InputStream?in=new?FileInputStream(file);
props.load(in);
Enumeration?en?=?props.propertyNames();
while?(en.hasMoreElements())?{
String?key?=?(String)?en.nextElement();
String?value?=?props.getProperty(key);
map.put(key,?value);//把properties文件中的key-value存放到一個(gè)map中
}
return?map;
}?catch?(Exception?e)?{
e.printStackTrace();
}
return?null;
}
public?static?String?replaceCheck(Map?map,String?name)?{
Setkeys?=?map.keySet();
Iteratoriter?=?keys.iterator();
while?(iter.hasNext())?{
String?key?=?iter.next();
String?value?=?(String)?map.get(key);
if?(name.contains(key))?{
name=name.replace(key,?value);//對(duì)于符合map中的key值實(shí)現(xiàn)替換功能
}
}
return?name;
}
}這里我把從properties文件中讀取的key--value的形式都存放到一個(gè)map對(duì)象中,方法都用static關(guān)鍵字,方便調(diào)用。
? ? 然后寫了個(gè)KeyWordRequestWrapper來(lái)繼承HttpServletRequestWrapper,實(shí)現(xiàn)包裝request對(duì)象的作用。
package?com.lhwl.elt.filter;
import?java.util.Iterator;
import?java.util.Map;
import?java.util.Set;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletRequestWrapper;
public?final?class?KeyWordRequestWrapper?extends?HttpServletRequestWrapper{
public?Map?keyMap;
public?KeyWordRequestWrapper(HttpServletRequest?servletRequest,Map?keyMap){
super(servletRequest);
this.keyMap?=?keyMap;
}
@Override
public?Map?getParameterMap()?{
super.getContextPath();
Mapmap?=?super.getParameterMap();
if(!map.isEmpty()){
SetkeySet?=?map.keySet();
IteratorkeyIt?=?keySet.iterator();
while(keyIt.hasNext()){
String?key?=?keyIt.next();
// String?value?=?map.get(key)[0];
// map.get(key)[0]?=?this.replaceParam(value);
//這邊實(shí)現(xiàn)對(duì)整個(gè)數(shù)組的判斷。
String[]?values=map.get(key);
for(int?i=0;i<values.length;i++){
map.get(key)[i]=this.replaceParam(values[i]);
}
}
}
return?map;
}
/* @Override
public?String[]?getParameterValues(String?name)?{
//?TODO?Auto-generated?method?stub
String[]?resources?=?super.getParameterValues(name);?
if?(resources?==?null)?
return?null;?
int?count?=?resources.length;?
String[]?results?=?new?String[count];?
for?(int?i?=?0;?i?<?count;?i++)?{?
results[i]?=?this.replaceParam(resources[i]);?
}?
return?results;?
}*/
public?String?replaceParam(String?name){
return?PropertiesUtil.replaceCheck(keyMap,name);
}
}這里由于本人項(xiàng)目的框架原因,框架的request都是使用的getParameterMap來(lái)獲取的,經(jīng)過(guò)處理了,所以沒(méi)有使用 getParameterValues,可以看到代碼中注釋掉的方法。覆寫了ServletRequestWrapper中的 getParameterMap方法來(lái)實(shí)現(xiàn)包裝功能,一般情況下,提交的value數(shù)組都只有一個(gè),String value = map.get(key)[0];map.get(key)[0] = this.replaceParam(value);即可滿足要求,但為了不出情況,還是實(shí)現(xiàn)了對(duì)整個(gè)數(shù)組的過(guò)濾替換功能。
?? 還剩個(gè)filter來(lái)實(shí)現(xiàn)了,先看具體的filter代碼:
package?com.lhwl.elt.filter;
import?java.io.IOException;
import?java.util.HashMap;
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.HttpServletRequest;
public?class?KeyWordFilter?implements?Filter{
private?FilterConfig?filterConfig;
public?static?HashMap?keyMap?=?null;
public?static?String?path;
@Override
public?void?init(FilterConfig?filterConfig)?throws?ServletException?{
this.filterConfig=filterConfig;
String?keyWordPath?=?filterConfig.getInitParameter("key");
path?=?filterConfig.getServletContext().getRealPath(keyWordPath);
}
@Override
public?void?doFilter(ServletRequest?request,?ServletResponse?response,?
FilterChain?chain)?throws?IOException,?ServletException?{
HttpServletRequest?req?=?(HttpServletRequest)request;
if(keyMap?==?null){
keyMap?=?(HashMap)PropertiesUtil.readProperties(path);
}
if(req.getMethod().equals("POST")){
chain.doFilter(new?KeyWordRequestWrapper(req,keyMap),?response);
}else{
chain.doFilter(request,?response);
}
}
@Override
public?void?destroy()?{
this.filterConfig?=?null;?
}
}這里在filter初始化的時(shí)候,就獲得項(xiàng)目的真實(shí)路徑,然后把最先定義的keyword.properties文件放到WEB-INF目錄下,定義一個(gè) keyWordPath,然后就可以通過(guò)在web.xml文件中配置init-param來(lái)注入。這里把keyMap和path都定義為static,這 樣只需要在加載的時(shí)候一次初始化就好了。chain.doFilter(new KeyWordRequestWrapper(req,keyMap), response);對(duì)于需要過(guò)濾的內(nèi)容進(jìn)行處理關(guān)鍵字,敏感字等,其他的則正常chain.doFilter(request, response); 最后再web.xml中配置這個(gè)filter就可以,注意配置的順序不要和其他filter沖突就行。web.xml配置:
keyWordFiltercom.lhwl.elt.filter.KeyWordFilterkey/WEB-INF/keyword.propertieskeyWordFilter/*
OK,現(xiàn)在只要輸入些properties文件中定義好要替換的內(nèi)容,則自動(dòng)的實(shí)現(xiàn)了替換功能。比如輸入fuck,提交顯示出來(lái)的就變成了**,對(duì)輸入的一些js腳本也能夠當(dāng)成文本顯示出來(lái)了。。。





