提交的表單數據,常常要檢查有沒有敏感辭彙,如果有,需要給出提示,或者替換為*。 檢查、替換敏感辭彙有3種常用的方式 (1)在Servlet中操作。 (2)在Filter中先檢查。如果要替換敏感辭彙,request沒有setParameter()方法重新設置請求參數,怎麼向Servlet中傳遞替換後的 ...
提交的表單數據,常常要檢查有沒有敏感辭彙,如果有,需要給出提示,或者替換為*。
檢查、替換敏感辭彙有3種常用的方式
(1)在Servlet中操作。
(2)在Filter中先檢查。如果要替換敏感辭彙,request沒有setParameter()方法重新設置請求參數,怎麼向Servlet中傳遞替換後的請求參數?使用request.setAttribute()把這些修改後的請求參數放到request域中即可。
(3)在Filter中創建request的代理,增強getParameter()方法,然後傳入代理: chain.doFilter(request的代理對象 resp); 。如何增強getParameter()方法?getParameter()不是要返回一個String嗎,先調用原來的getParameter()獲取值,檢查值中是否有敏感辭彙,有就替換掉敏感辭彙,返回替換後的值,沒有敏感辭彙就返回原值。
(1)、(2)較簡單,但很繁瑣,(3)最常用。此處只演示(3)。
敏感辭彙
敏感辭彙很多,可以存儲在資料庫中,也可以存儲在文本文件中。
此處我們在項目根目錄下新建文件夾resource,標識為資源根目錄。resource下新建 illegal_word.txt 存儲敏感辭彙,一行一個。
煞筆
制杖
cxk
每次都從資料庫讀或文件取讀敏感辭彙,會增加時間開銷,可以把取敏感辭彙放到ServletContext中,全局共用、隨時可用。
怎麼放?Filter的init()方法在Filter生命周期中只調用一次,可以在init()中讀取敏感辭彙,將敏感辭彙放到ArrayList<String>中,再將這個list放到ServletContext中,這樣避免了每訪問一次就讀取一次的問題。
表單
<form action="handlerServlet" method="post"> 評論:<textarea name="comment" rows="10" cols="50"></textarea> <button type="submit">提交</button> </form>
Filter
@WebFilter("/handlerServlet") public class HandlerFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //解決中文亂碼 req.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); //jdk動態代理 ClassLoader classLoader = req.getClass().getClassLoader(); Class<?>[] interfaces = req.getClass().getInterfaces(); //創建InvocationHandler介面的實例。此處使用匿名內部類來創建 InvocationHandler invocationHandler = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //只增強getParameter() if(method.getName().equals("getParameter")){ //調用原有的getParameter()獲取參數值 String text = (String) method.invoke(req, args); //檢查是否有敏感辭彙 Object obj = req.getServletContext().getAttribute("illegal_word_list"); ArrayList<String> list=(ArrayList<String>)obj; for (String word : list){ if (text.contains(word)){ //用一個*替換一個字元 String replac=""; for(int i=0;i<word.length();i++){ replac+="*"; } //替換所有匹配 text = text.replaceAll(word, replac); } } return text; } //如果調用的是getParameter(),執行到前面的return就結束了,不會執行到此 //如果調用的不是getParameter(),就調用原方法,不做修改 Object returnValue=method.invoke(req,args); //調用目標方法 return returnValue; } }; //創建req的代理對象 Object proxyInstance = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); //強轉為ServletRequest ServletRequest reqProxyInstance = (ServletRequest) proxyInstance; //傳入req的代理對象 chain.doFilter(reqProxyInstance, resp); } public void init(FilterConfig config) throws ServletException { InputStream is= this.getClass().getResourceAsStream("/illegal_word.txt"); //因為要readLine()一行一行地讀,需要使用BufferedReader流,所以先轉換為Reader,再加Buffer InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); ArrayList<String> list=new ArrayList<>(); String str=null; while (true){ try { str=br.readLine(); if (str!=null) list.add(str); else break; } catch (IOException e) { e.printStackTrace(); } } //放到ServletContext中 config.getServletContext().setAttribute("illegal_word_list",list); } }
測試用的Servlet
@WebServlet("/handlerServlet") public class HandlerServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String comment = request.getParameter("comment"); response.getWriter().write(comment); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } }
效果
這種方式是增強getParameter(),通過getParameter()獲取參數值時,都會先自動檢測是否有敏感辭彙。