最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springboot詳解如何實(shí)現(xiàn)SQL注入過(guò)濾器過(guò)程

 更新時(shí)間:2022年06月17日 10:36:40   作者:zhangbeizhen18  
這篇文章主要介紹了基于springboot實(shí)現(xiàn)SQL注入過(guò)濾器,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

場(chǎng)景:以過(guò)濾器(Filter)的方式,對(duì)所有http請(qǐng)求的入?yún)r截,使用正則表達(dá)式匹配入?yún)⒅械淖址4嬖赟QL注入風(fēng)險(xiǎn)的參數(shù),中斷請(qǐng)求,并立即返回提示信息。不存在SQL注入風(fēng)險(xiǎn)的參數(shù),校驗(yàn)通過(guò)后,放入過(guò)濾器鏈,繼續(xù)后續(xù)業(yè)務(wù)。

環(huán)境:本例是基于springboot的web工程,版本:springboot 2.6.3

1.過(guò)濾器SqlInjectFilter

SqlInjectFilter,實(shí)現(xiàn)javax.servlet.Filter接口。即在doFilter方法中實(shí)現(xiàn)具體邏輯。

@Slf4j
public class SqlInjectFilter implements Filter {
  private static final String SQL_REG_EXP = ".*(\\b(select|insert|into|update|delete|from|where|and|or|trancate" +
      "|drop|execute|like|grant|use|union|order|by)\\b).*";
  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) servletRequest;
    CustomRequestWrapper requestWrapper = new CustomRequestWrapper(request);
    Map<String, Object> parameterMap = new HashMap<>();
    parameterMap =getParameterMap(parameterMap, request, requestWrapper);
    // 正則校驗(yàn)是否有SQL關(guān)鍵字
    for (Object obj : parameterMap.entrySet()) {
        Map.Entry entry = (Map.Entry) obj;
        Object value = entry.getValue();
        if (value != null) {
            boolean isValid = isSqlInject(value.toString(), servletResponse);
            if (!isValid) {
                return;
            }
        }
    }
    filterChain.doFilter(requestWrapper, servletResponse);
  }
  private Map<String, Object> getParameterMap(Map<String, Object> paramMap, HttpServletRequest request, CustomRequestWrapper requestWrapper) {
    // 1.POST請(qǐng)求獲取參數(shù)
    if ("POST".equals(request.getMethod().toUpperCase())) {
        String body = requestWrapper.getBody();
        paramMap = JSONObject.parseObject(body, HashMap.class);
    } else {
        Map<String, String[]> parameterMap = requestWrapper.getParameterMap();
        //普通的GET請(qǐng)求
        if (parameterMap != null && parameterMap.size() > 0) {
            Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
            for (Map.Entry<String, String[]> next : entries) {
                paramMap.put(next.getKey(), next.getValue()[0]);
            }
        } else {
            //GET請(qǐng)求,參數(shù)在URL路徑型式,比如server/{var1}/{var2}
            String afterDecodeUrl = null;
            try {
                //編碼過(guò)URL需解碼解碼還原字符
                afterDecodeUrl = URLDecoder.decode(request.getRequestURI(), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            paramMap.put("pathVar", afterDecodeUrl);
        }
    }
    return paramMap;
  }
  private boolean isSqlInject(String value, ServletResponse servletResponse) throws IOException {
    if (null != value && value.toLowerCase().matches(SQL_REG_EXP)) {
      log.info("入?yún)⒅杏蟹欠ㄗ址? " + value);
      HttpServletResponse response = (HttpServletResponse) servletResponse;
      Map<String, String> responseMap = new HashMap<>();
      // 匹配到非法字符,立即返回
      responseMap.put("code", "999");
      responseMap.put("message","入?yún)⒅杏蟹欠ㄗ址?);
      response.setContentType("application/json;charset=UTF-8");
      response.setStatus(HttpStatus.OK.value());
      response.getWriter().write(JSON.toJSONString(responseMap));
      response.getWriter().flush();
      response.getWriter().close();
      return false;
    }
    return true;
  }
}

2.請(qǐng)求裝飾類CustomRequestWrapper

在攔截請(qǐng)求時(shí),會(huì)讀取HttpServletRequest的InputStream,而這種數(shù)據(jù)流一旦讀取后,就沒(méi)了。那么直接把請(qǐng)求放入過(guò)濾器鏈,后續(xù)的環(huán)節(jié)就讀取不到數(shù)據(jù)了。因此,需要一個(gè)裝飾類,讀取了InputStream數(shù)據(jù)后,還得回寫到請(qǐng)求中。然后把數(shù)據(jù)完整的裝飾類放入過(guò)濾器鏈。這樣攔截了請(qǐng)求,讀取了數(shù)據(jù),并回寫了數(shù)據(jù),數(shù)據(jù)完整性得到保證。

public class CustomRequestWrapper extends HttpServletRequestWrapper {
  private final String body;
  public CustomRequestWrapper(HttpServletRequest request) throws IOException {
    super(request);
    StringBuilder sb = new StringBuilder();
    BufferedReader bufferedReader = null;
    try {
      InputStream inputStream = request.getInputStream();
      if (inputStream != null) {
          bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
          char[] charBuffer = new char[512];
          int bytesRead = -1;
          while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
              sb.append(charBuffer, 0, bytesRead);
          }
      } else {
          sb.append("");
      }
    } catch (IOException e) {
      e.printStackTrace();
      throw e;
    } finally {
      if (bufferedReader != null) {
      try {
          bufferedReader.close();
      } catch (IOException e) {
          e.printStackTrace();
          throw e;
      }
      }
    }
    body = sb.toString();
  }
  @Override
  public ServletInputStream getInputStream() throws IOException {
    final ByteArrayInputStream bais = new ByteArrayInputStream(body.getBytes("UTF-8"));
    return new ServletInputStream() {
      @Override
      public boolean isFinished() {
          return false;
      }
      @Override
      public boolean isReady() {
          return false;
      }
      @Override
      public void setReadListener(ReadListener readListener) {
      }
      @Override
      public int read() {
          return bais.read();
      }
    };
  }
  @Override
  public BufferedReader getReader() throws IOException {
    return new BufferedReader(new InputStreamReader(this.getInputStream(), StandardCharsets.UTF_8));
  }
  public String getBody() {
    return this.body;
  }
  @Override
  public String getParameter(String name) {
    return super.getParameter(name);
  }
  @Override
  public Map<String, String[]> getParameterMap() {
    return super.getParameterMap();
  }
  @Override
  public Enumeration<String> getParameterNames() {
    return super.getParameterNames();
  }
  @Override
  public String[] getParameterValues(String name) {
    return super.getParameterValues(name);
  }
}

3.過(guò)濾器注冊(cè)

過(guò)濾器生效,需注冊(cè)。

@Configuration
public class FilterConfiguration {
  @Bean("sqlFilter")
  public SqlInjectFilter sqlInjectFilter() {
    return new SqlInjectFilter();
  }
  @Bean
  public FilterRegistrationBean<SqlInjectFilter> sqlFilterRegistrationBean() {
    FilterRegistrationBean<SqlInjectFilter> filterReg = new FilterRegistrationBean<>();
    filterReg.setFilter(sqlInjectFilter());
    filterReg.addUrlPatterns("/*");
    filterReg.setOrder(1);
    return filterReg;
  }
}

4.測(cè)試輔助類

4.1 結(jié)果對(duì)象ResultObj

Restful請(qǐng)求返回格式統(tǒng)一。

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ResultObj {
    private String code;
    private String message;
}

4.2 Restful的Controller類

SqlInjectionController,包括POST請(qǐng)求和GET請(qǐng)求測(cè)試。

@RestController
@Slf4j
@RequestMapping("/inject")
public class SqlInjectionController {
  @PostMapping("/f1")
  public Object f1(@RequestBody Object obj) {
    log.info("SqlInjectionController->f1,接收參數(shù),obj = " + obj.toString());
    log.info("SqlInjectionController->f1,返回.");
    return ResultObj.builder().code("200").message("成功").build();
  }
  @GetMapping("/f2")
  public Object f2(@RequestParam(name = "var") String var) {
    log.info("SqlInjectionController->f2,接收參數(shù),var = " + var);
    log.info("SqlInjectionController->f2,返回.");
    return ResultObj.builder().code("200").message("成功").build();
  }
  @GetMapping("/f3/{var}")
  public Object f3(@PathVariable("var") String var) {
    log.info("SqlInjectionController->f3,接收參數(shù),var = " + var);
    log.info("SqlInjectionController->f3,返回.");
    return ResultObj.builder().code("200").message("成功").build();
  }
}

5.測(cè)試

5.1 POST請(qǐng)求測(cè)試

URL: http://127.0.0.1:18081/server/inject/f1

入?yún)ⅲ?/p>

{
  "userName": "Hangzhou select",
  "password": "202206112219"
}

返回:

{
  "code": "999",
  "message": "入?yún)⒅杏蟹欠ㄗ址?quot;
}

5.2 GET請(qǐng)求測(cè)試1

URL: http://127.0.0.1:18081/server/inject/f2?var=56622 INSert

返回:

{
  "code": "999",
  "message": "入?yún)⒅杏蟹欠ㄗ址?quot;
}

5.3 GET請(qǐng)求測(cè)試2

URL: http://127.0.0.1:18081/server/inject/f3/123 delete

返回:

{
  "code": "999",
  "message": "入?yún)⒅杏蟹欠ㄗ址?quot;
}

到此這篇關(guān)于Springboot詳解如何實(shí)現(xiàn)SQL注入過(guò)濾器過(guò)程的文章就介紹到這了,更多相關(guān)Springboot SQL注入過(guò)濾器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java讀取wav文件(波形文件)并繪制波形圖的方法

    java讀取wav文件(波形文件)并繪制波形圖的方法

    這篇文章主要介紹了java讀取wav文件(波形文件)并繪制波形圖的方法,涉及java操作多媒體音頻文件轉(zhuǎn)換的相關(guān)技巧,需要的朋友可以參考下
    2015-06-06
  • IDEA連接Mysql數(shù)據(jù)庫(kù)的詳細(xì)圖文教程

    IDEA連接Mysql數(shù)據(jù)庫(kù)的詳細(xì)圖文教程

    項(xiàng)目開發(fā)時(shí)使用Intellij IDEA連接本地?cái)?shù)據(jù)庫(kù),將數(shù)據(jù)庫(kù)可視化,還可對(duì)數(shù)據(jù)庫(kù)表直接進(jìn)行增刪改查操作,方便快捷又清晰,下面這篇文章主要給大家介紹了關(guān)于IDEA連接Mysql數(shù)據(jù)庫(kù)的詳細(xì)圖文教程,需要的朋友可以參考下
    2023-03-03
  • 使用@RequestBody配合@Valid校驗(yàn)入?yún)?shù)

    使用@RequestBody配合@Valid校驗(yàn)入?yún)?shù)

    這篇文章主要介紹了使用@RequestBody配合@Valid校驗(yàn)入?yún)?shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 詳解java爬蟲jsoup解析多空格class數(shù)據(jù)

    詳解java爬蟲jsoup解析多空格class數(shù)據(jù)

    在本篇內(nèi)容中小編給大家分享了java爬蟲jsoup怎么解析多空格class數(shù)據(jù)的方法和技巧,需要的朋友們跟著學(xué)習(xí)下。
    2018-12-12
  • Spring Cloud Alibaba配置多環(huán)境管理詳解與實(shí)戰(zhàn)代碼

    Spring Cloud Alibaba配置多環(huán)境管理詳解與實(shí)戰(zhàn)代碼

    本文通過(guò)實(shí)際案例詳細(xì)介紹了springboot配置多環(huán)境管理的使用,以及基于nacos的配置多環(huán)境管理的實(shí)踐,在實(shí)際開發(fā)中,配置多環(huán)境管理是一個(gè)很難避開的問(wèn)題,同時(shí)也是微服務(wù)治理中一個(gè)很重要的內(nèi)容,感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • 聊聊Spring循環(huán)依賴三級(jí)緩存是否可以減少為二級(jí)緩存的情況

    聊聊Spring循環(huán)依賴三級(jí)緩存是否可以減少為二級(jí)緩存的情況

    這篇文章主要介紹了聊聊Spring循環(huán)依賴三級(jí)緩存是否可以減少為二級(jí)緩存的情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • 簡(jiǎn)單了解java函數(shù)式編碼結(jié)構(gòu)及優(yōu)勢(shì)

    簡(jiǎn)單了解java函數(shù)式編碼結(jié)構(gòu)及優(yōu)勢(shì)

    這篇文章主要介紹了簡(jiǎn)單了解java函數(shù)式編碼結(jié)構(gòu)及優(yōu)勢(shì),本文將探討三種下一代 JVM 語(yǔ)言:Groovy、Scala 和 Clojure,比較并對(duì)比新的功能和范例,讓 Java 開發(fā)人員對(duì)自己近期的未來(lái)發(fā)展有大體的認(rèn)識(shí)。,需要的朋友可以參考下
    2019-06-06
  • Spring Boot 3.x 全新的熱部署配置方式詳解(IntelliJ IDEA 2023.1)

    Spring Boot 3.x 全新的熱部署配置方式詳解(IntelliJ ID

    這篇文章主要介紹了Spring Boot 3.x 全新的熱部署配置方式(IntelliJ IDEA 2023.1),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • 教你如何使用JAVA POI

    教你如何使用JAVA POI

    今天教大家怎么學(xué)習(xí)JAVA POI的用法,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05
  • Java實(shí)現(xiàn)經(jīng)典游戲俄羅斯方塊(升級(jí)版)的示例代碼

    Java實(shí)現(xiàn)經(jīng)典游戲俄羅斯方塊(升級(jí)版)的示例代碼

    俄羅斯方塊是一款風(fēng)靡全球,從一開始到現(xiàn)在都一直經(jīng)久不衰的電腦、手機(jī)、掌上游戲機(jī)產(chǎn)品,是一款游戲規(guī)則簡(jiǎn)單,但又不缺乏樂(lè)趣的簡(jiǎn)單經(jīng)典小游戲。本文將用Java語(yǔ)言實(shí)現(xiàn)這一經(jīng)典游戲,需要的可以參考一下
    2022-09-09

最新評(píng)論

连城县| 绥中县| 华阴市| 桦川县| 济宁市| 龙胜| 舒兰市| 郧西县| 沧州市| 读书| 泸州市| 读书| 德昌县| 仙居县| 司法| 台前县| 论坛| 简阳市| 合作市| 利辛县| 河池市| 怀柔区| 新乐市| 仙桃市| 阳东县| 出国| 安岳县| 连江县| 自贡市| 神池县| 方山县| 朝阳县| 乡城县| 应城市| 两当县| 大渡口区| 宜君县| 黑山县| 临夏市| 沛县| 肇东市|