過濾器Filter案例-實作敏感詞彙過濾
Filter概念: web中的過濾器:當通路伺服器的資源時,過濾器可以将請求攔截下來,完成一些特殊的功能。
過濾器的作用:
- 一般用于完成通用的操作,如:登陸驗證,統一編碼處理、敏感字元過濾…等。
- Filter過濾器能夠在Servlet被調用之前檢查Request對象,并修改Request Header和Request内容;在Servlet被調用之後檢查Response對象,修改Response Header和Response的内容,實作多次過濾。
- Filter可以過濾的web元件包括Servlet,JSP和HTML等檔案。
Filter的過濾原理
當浏覽器向伺服器發出資源的請求時,當浏覽器滿足過濾條件時,Web伺服器根據應用程式配置檔案設定的過濾規則進行檢查。是一次雙向過濾的過程
過濾器生命周期方法
init()方法:在伺服器啟動後,會建立filter對象,然後調用init方法。隻執行一次,用于加載資源。
doFilter()方法:每一次請求被攔截資源時,會執行,執行多次。
destroy()方法:在伺服器關閉後,filter對象會被銷毀,如果伺服器時正常關閉,則會執行destroy方法,隻執行一次,用于釋放資源。
過濾器鍊(配置多個過濾器)
執行順序:如果有兩個過濾器:過濾器1,過濾器2
過濾器1–>過濾器2–>資源執行–>(傳回)–>過濾器2–>過濾1
過濾器先後順序問題:
注解配置:按照類名的字元串比較規則比較,值小的先執行。
如:Afilter 和 Bfilter,A<B A先執行
過濾器配置
攔截方式配置:dispatcherTypes 資源通路的方式:
//假如時浏覽器直接請求index.jsp路徑,那麼将直接攔截,轉發到該路徑則不予阻攔
@WebFilter(value = "/index.jsp", dispatcherTypes = DispatcherType.REQUEST)
//釋放代碼
chain.doFilter(req, resp);
案例敏感詞的過濾:
代理模式詳解圖:(靈魂畫手)、反正意思就似乎用上代理類,效率高,還能過濾掉敏感詞彙
為什麼要用代理模式?
中介隔離作用:在某些情況下,一個客戶類不想或者不能直接引用一個委托對象,而代理類對象可以在客戶類和委托對象之間起到中介的作用,其特征是代理類和委托類實作相同的接口。
接下來就是實作代理模式
** public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
String name = req.getParameter("name");
//動态代理增強,增強getParameter方法
/* 三個參數:
1. 類加載器:真實對象.getClass().getClassLoader()
2. 接口數組:真實對象.getClass().getInterfaces()
3. 處理器:new InvocationHandler()
這邊的真實對象就是ServletRequest req的參數;
*/
ServletRequest ser = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/* 代理邏輯編寫的方法:代理對象調用的所有方法都會觸發該方法執行
參數:1. proxy:代理對象
2. method:代理對象調用的方法,被封裝為的對象
3. args:代理對象調用的方法時,傳遞的實際參數
*/
//判斷是不是getParameter方法
if (method.getName().equals("getParameter")){
//使用真實對象調用該方法
String invoke = (String) method.invoke(req, args);
//假如傳回的值不為空,則進行敏感字元過濾
if (invoke != null ){
for (String s : list) {
if (invoke.contains(s)){
invoke = invoke.replaceAll(s,"***");
}
}
}
return invoke;
}
return method.invoke(req,args);
}
});
String name1 = ser.getParameter("name");
String rows = ser.getParameter("rows");
System.out.println(rows);
chain.doFilter(ser, resp);
}
//init方法在第一時間進行執行,并且隻會執行一次。把每對敏感字元存入到list集合中
private List<String> list = new ArrayList<>();
@Override
public void init(FilterConfig config) throws ServletException {
//擷取路徑
try {
ServletContext servletContext = config.getServletContext();
String realPath = servletContext.getRealPath("//WEB-INF//classes//敏感詞彙.txt");
//防止亂碼 用InputStreamReade是從位元組流到字元流的橋梁。
BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream(realPath),"gbk"));
String len = null;
while ((len = bufr.readLine()) != null){
list.add(len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}**
效果展示:
你是壞蛋,王八蛋
你是***,***
你是***,***