SQL注入和SCRIPT注入,是一個(gè)煩人的東西,那么這個(gè)問題該怎么解決呢?下面就說一說如何解決這個(gè)問題。
              在項(xiàng)目一開始,如果就考慮到這個(gè)問題的話,那是可以完全避免的。
              反script注入:在jsp頁面中解決,增刪查修審都用struts標(biāo)簽 ,是沒有任何問題的。如果是html標(biāo)簽的話,用jstl標(biāo)簽也可以完全解決。
              那么如果用到文本編輯器的時(shí)候,又該怎么解決啊?我的反SCRIPT注入就可以解決這個(gè)問題了。
              反sql注入:如果是jdbc的話,不要用Statement,用PreparedStatement就可以避免。如果用hibernate的話,用 Criteria查詢就可以解決這個(gè)問題。

              如何是在項(xiàng)目快完結(jié)的時(shí)候才發(fā)現(xiàn)這個(gè)問題,那該怎么解決???
              apache提供了工具類:org.apache.commons.lang.StringEscapeUtils,它里面有對(duì)應(yīng)的方法解決這個(gè)問題。
              下面是我自己提供一種方法。

              為了實(shí)現(xiàn)反SQL注入和反SCRIPT注入,本例應(yīng)用反射技術(shù)和責(zé)任鏈模式實(shí)現(xiàn)了這個(gè)功能。它對(duì)于系統(tǒng)來說是可插撥的,這樣就實(shí)現(xiàn)了與系統(tǒng)的松散耦合。
              它的主要思想是:把Form對(duì)象,PO對(duì)象以及VO等對(duì)象中的String型屬性的值或者String類型的參數(shù)進(jìn)行過濾后重新封裝為原有類型的對(duì)象。在獲取對(duì)象的時(shí)候應(yīng)用了 java反映技術(shù),
          在進(jìn)行過濾的時(shí)候,實(shí)現(xiàn)了鏈?zhǔn)竭^濾。這樣做,就是為了達(dá)到可維護(hù)性,可擴(kuò)展性,可重用性以及靈活性的目的。
              以下是源代碼:


          package net.better_best.www.utils.filter;
          public class Request {
              // 存儲(chǔ)需要過濾的字符串
              private String requestStr;
              public String getRequestStr() {
                  return requestStr;
              }
              public void setRequestStr(String requestStr) {
                  this.requestStr = requestStr;
              }
          }


          package net.better_best.www.utils.filter;

          public class FilterConstant {
           //定義sql過濾的內(nèi)容
           public static String[][] SQL_FILTER = {
            {";",""},
            {"'","''"},
            {"--",""},
            {"%",""}
            };
            //定義script過濾的內(nèi)容
           public static String[][] SCRIPT_FILTER = {
            {"(<[i|I][n|N][p|P][u|U][t|T])([^>]*)(/>)",""},
            {"(<[i|I][n|N][p|P][u|U][t|T])([\\s\\S]*)(</[i|I][n|N][p|P][u|U][t|T]>)",""},
            {"(<[t|T][a|A][b|B][l|L][e|E])([^>]*)(/>)",""},
            {"(<[t|T][a|A][b|B][l|L][e|E])([\\s\\S]*)(</[t|T][a|A][b|B][l|L][e|E]>)",""},
            {"(<[d|D][i|I][v|V])([^>]*)(/>)",""},
            {"(<[d|D][i|I][v|V])([\\s\\S]*)(</[d|D][i|I][v|V]>)",""},
            {"(<[b|B][u|U][t|T][t|T][o|O][n|N])([^>]*)(/>)",""},
            {"(<[b|B][u|U][t|T][t|T][o|O][n|N])([\\s\\S]*)(</[b|B][u|U][t|T][t|T][o|O][n|N]>)",""},
            {"(<[s|S][c|C][r|R][i|I][p|P][t|T])([^>]*)(/>)",""},
            {"(<[s|S][c|C][r|R][i|I][p|P][t|T])([\\s\\S]*)(</[s|S][c|C][r|R][i|I][p|P][t|T])(>)",""},
            };
          }



          package net.better_best.www.utils.filter;

          public interface IFilter {
              void doFilter(Request request, FilterChain chain);
          }



           

          package net.better_best.www.utils.filter;

          public class SqlFilter implements IFilter {
              @Override
              //進(jìn)行sql過濾
              public void doFilter(Request request, FilterChain chain) {
                  if (request != null) {
                   String strRequest = request.getRequestStr();
                   String[][] sqlFilter = FilterConstant.SQL_FILTER;
                   for (String[] strings : sqlFilter) {
                    strRequest = strRequest.replace(strings[0], strings[1]);
             }
                   request.setRequestStr(strRequest);
                  }
                  chain.doFilter(request, chain);
               
              }
          }




          package net.better_best.www.utils.filter;

          public class ScriptFilter implements IFilter {
           @Override
           //進(jìn)行script過濾
           public void doFilter(Request request, FilterChain chain) {
            if (request != null) {
             String strRequest = request.getRequestStr();
             String[][] scriptFilter = FilterConstant.SCRIPT_FILTER;
                   for (String[] strings : scriptFilter) {
                    strRequest = strRequest.replaceAll(strings[0], strings[1]);
             }
             request.setRequestStr(strRequest);
            }
            chain.doFilter(request, chain);

           }
          }




          package net.better_best.www.utils.filter;

          public enum FilterType {
           SQL_TYPE,SCRIPT_TYPE ;
          }


          package net.better_best.www.utils.filter;


          public class FilterHelper {
           /*
            * 生成過濾鏈條 參數(shù):String type:過濾類型 返回:FilterChain; 根據(jù)過濾類型產(chǎn)生過濾鏈條
            */
           public static FilterChain createFilterChain(FilterType type,FilterChain fChain) throws Exception {
            if (type == null)
             return null;
            else if (type.equals(FilterType.SQL_TYPE))
             return fChain.addFilter(new SqlFilter());
            else if (type.equals(FilterType.SCRIPT_TYPE))
             return fChain.addFilter(new ScriptFilter());
            else
             return null;
           }

           /*
            * 把要過濾的字符串封裝成Request對(duì)象
            */
           public static Request init(String str) throws Exception {
            if (str == null || str == "")
             return null;
            Request request = new Request();
            request.setRequestStr(str);
            return request;
           }

           /*
            * 對(duì)Request對(duì)象進(jìn)行循環(huán)過濾
            */
           public static String result(Request request, FilterChain fChain)
             throws Exception {
            if (request == null || fChain == null || fChain.size() == 0)
             return null;
            fChain.doFilter(request, fChain);
            return request.getRequestStr();
           }
          }


          package net.better_best.www.utils.filter;
          import java.util.ArrayList;
          import java.util.List;

          public class FilterChain implements IFilter {
              // 使用 List 保存過濾器
              private List<IFilter> filters = new ArrayList<IFilter>();
              private int index = 0;
              // 用于添加過濾器,可以添加實(shí)現(xiàn)了IFilter接口的FilterChain
              public FilterChain addFilter(IFilter f) {
                  this.filters.add(f);
                  return this;
              }
              @Override
              public void doFilter(Request request,  FilterChain chain) {
                  // 判斷是否是否遍歷到 List 的最大值,如果是 return
                  if (index == filters.size())
                      return;
                  // 逐一獲取過濾器
                  IFilter f = filters.get(index);
                  // 此過濾器鏈的下標(biāo),是遍歷過濾器的索引
                  index++;
                  // 使用列表中的第index個(gè)過濾器,將更改后的 request ,chain 傳進(jìn)去,
                  f.doFilter(request,chain);
                  index = 0;
              }
              public int size(){
               return filters.size();
              }
          }


          package net.better_best.www.utils;

          import java.lang.reflect.Field;

          import net.better_best.www.utils.filter.FilterChain;
          import net.better_best.www.utils.filter.FilterHelper;
          import net.better_best.www.utils.filter.FilterType;

          public class Filter {
           /*
            * 參數(shù):Object,接收ActionForm,Plain Object,View.Object的屬性值應(yīng)為單值類型,不能為復(fù)合類型或數(shù)組類型;
            * 參數(shù):FilterType,定義需要過濾的類型; 返回值:Object; 作用:根據(jù)已定義的過濾規(guī)則,過濾所傳入Object值;
            */
           public static Object objectFilter(Object obj, FilterType... types) {
            if (obj == null)return obj;
            Class clazz = obj.getClass();
            if (clazz.isArray() || clazz.isInterface() || clazz.isPrimitive())return obj;
            Field[] fds = clazz.getDeclaredFields();
            for (Field field : fds) {
             if (field.getType().getName().equals("java.lang.String")) {
              field.setAccessible(true);
              Object before = null;
              try {
               before = field.get(obj);
              } catch (IllegalArgumentException e) {
               e.printStackTrace();
              } catch (IllegalAccessException e) {
               e.printStackTrace();
              }
              if (before != null)
               try {
                field.set(obj, doFilter(before.toString(), types));
               } catch (IllegalArgumentException e) {
                e.printStackTrace();
               } catch (IllegalAccessException e) {
                e.printStackTrace();
               }
             }
            }
            return obj;
           }

           /*
            * 按照定義好的過濾規(guī)則,進(jìn)行過濾; 參數(shù):String str ,待過濾字符串 返回:String; 已過濾字符串
            */
           public static String doFilter(String str, FilterType... types) {
            if (str == null || str == "")
             return null;
            FilterChain fChain = new FilterChain();
            String result = "";
            try {
             if (types.length == 0) {
              FilterType[] filterTypes = FilterType.values();
              for (FilterType filterType : filterTypes) {
               fChain = FilterHelper.createFilterChain(filterType, fChain);
              }
             } else {
              for (FilterType type : types) {
               fChain = FilterHelper.createFilterChain(type, fChain);
              }
             }
             if (fChain == null) {
              result = str;
             } else {
              result = FilterHelper.result(FilterHelper.init(str), fChain);
             }

            } catch (Exception e) {
             e.printStackTrace();
            }
            return result;
           }
          }



               使用方法:調(diào)用Filter的兩個(gè)方法,就可以了。

              以上內(nèi)容為全部代碼;


                歡迎對(duì)本文的內(nèi)容提出不同見解和質(zhì)疑,不勝感激。
                如果疑問,可發(fā)郵件聯(lián)系我??砂l(fā)郵件索取源代碼。
                



             

          Feedback

          # re: 反SQL注入和SCRIPT注入-------------責(zé)任鏈模式的應(yīng)用  回復(fù)  更多評(píng)論   

          2010-01-13 16:43 by 超級(jí)笨笨
          可以,對(duì)我有幫助

          # re: 反SQL注入和SCRIPT注入-------------責(zé)任鏈模式的應(yīng)用  回復(fù)  更多評(píng)論   

          2010-01-14 15:41 by Lancelot
          為什么要做這些無用功???

          正解應(yīng)該是表單提交時(shí),允許用戶提交各種數(shù)據(jù),通過“SET PARAMETER”方式傳入sql中(不管是自己,還是通過ORM都可以很容易實(shí)現(xiàn)),這樣來解決sql注入。

          至于script注入,只需要再在上面的基礎(chǔ)上,根據(jù)需要顯示出相應(yīng)的格式就可以了,比如:“jstl”的“out” 可以設(shè)置 “escapeXml”、“struts”的“write”可以設(shè)置“flter”。

          # re: 反SQL注入和SCRIPT注入-------------責(zé)任鏈模式的應(yīng)用  回復(fù)  更多評(píng)論   

          2010-01-15 11:19 by java小爬蟲
          @Lancelot
          你好,你說的東西,我都試過了,都是可以的。

          但是有一個(gè)問題:

          就是AJAX方式,查詢結(jié)果是用字符串拼接起來的,這種情況怎么解決?。课夷壳斑€沒有找到結(jié)果辦法。謝謝...

          # re: 反SQL注入和SCRIPT注入-------------責(zé)任鏈模式的應(yīng)用  回復(fù)  更多評(píng)論   

          2010-01-15 11:20 by java小爬蟲
          @超級(jí)笨笨
          歡迎對(duì)以上代碼挑刺...

          呵呵呵

          # re: 反SQL注入和SCRIPT注入-------------責(zé)任鏈模式的應(yīng)用  回復(fù)  更多評(píng)論   

          2010-01-15 11:53 by Lancelot
          以struts為例,只要調(diào)用org.apache.struts.util.ResponseUtils.filter(String value),方法就是了,有什么問題???

          # re: 反SQL注入和SCRIPT注入-------------責(zé)任鏈模式的應(yīng)用  回復(fù)  更多評(píng)論   

          2010-01-15 13:00 by java小爬蟲
          @Lancelot

          舉個(gè)例子:

          public ActionForward getNewsList(
          ActionMapping mapping, ActionForm form, HttpServletRequest request,
          HttpServletResponse response) {

          try {
          PrintWriter out = init(request, response);
          PageInfo pageinfo = newsService.getNewsPerPage(
          ParameterCode.curpage_first, ParameterCode.pageSize_10, "");
          List<NewsTable> newsList = pageinfo.getPagedata();
          if (newsList != null && newsList.size() > 0) {
          out.print("<UL>");
          for (NewsTable news : newsList) {

          out.print("<li>.<a href='aa.html' title='"
          + news.getNewsTitle() + "' >"
          + news.getNewsTitle() + "</a></li>");

          }
          out.print("</UL>");
          out.close();
          }
          }
          catch (Exception e) {

          e.printStackTrace();
          }
          return null;
          }


          ajax會(huì)調(diào)用這個(gè)方法,那么org.apache.struts.util.ResponseUtils.filter(news.getNewsTitle())就這樣過濾嗎?

          # re: 反SQL注入和SCRIPT注入-------------責(zé)任鏈模式的應(yīng)用  回復(fù)  更多評(píng)論   

          2010-01-15 13:57 by Lancelot
          雖然不贊成你這種寫法,不過在你這中應(yīng)用場景里就是這么用,這總比你費(fèi)盡周折的造出那么個(gè)東西來的要好。

          # re: 反SQL注入和SCRIPT注入-------------責(zé)任鏈模式的應(yīng)用  回復(fù)  更多評(píng)論   

          2010-01-15 18:05 by java小爬蟲
          @Lancelot
          其實(shí),在項(xiàng)目開始的時(shí)候,就考慮script和sql注入,是可以完全避免這個(gè)問題的。


          但是如果到了項(xiàng)目后期的話,我這個(gè)東西還是可是用的,自我感覺良好,還可以用于系統(tǒng)定義的非法字符的過濾,呵呵呵,


          不過,你的建議讓我學(xué)到了不少東西,謝謝你...

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 东宁县| 荔波县| 和硕县| 蓬安县| 新巴尔虎右旗| 疏勒县| 门头沟区| 福建省| 长宁区| SHOW| 天全县| 夏河县| 铜鼓县| 石柱| 精河县| 建宁县| 张掖市| 虎林市| 荃湾区| 新余市| 精河县| 霍林郭勒市| 沙雅县| 余干县| 四会市| 佳木斯市| 大兴区| 朝阳县| 荆州市| 略阳县| 泽普县| 河北省| 报价| 衡水市| 文水县| 青铜峡市| 剑阁县| 高邑县| 金塔县| 泸溪县| 云和县|