欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot2.x 整合 AntiSamy防御XSS攻擊的簡單總結(jié)

 更新時間:2021年08月26日 11:54:22   作者:RtxTitanV  
本文主要對SpringBoot2.x集成AntiSamy防御XSS攻擊進行簡單總結(jié),其中SpringBoot使用的2.4.5版本,通過示例代碼給大家介紹的非常詳細,需要的朋友參考下吧

AntiSamy是OWASP的一個開源項目,通過對用戶輸入的HTML、CSS、JavaScript等內(nèi)容進行檢驗和清理,確保輸入符合應(yīng)用規(guī)范。AntiSamy被廣泛應(yīng)用于Web服務(wù)對存儲型和反射型XSS的防御中。

XSS攻擊全稱為跨站腳本攻擊(Cross Site Scripting),是一種在web應(yīng)用中的計算機安全漏洞,它允許用戶將惡意代碼(如script腳本)植入到Web頁面中,為了不和層疊樣式表(Cascading Style Sheets, CSS)混淆,一般縮寫為XSS。XSS分為以下兩種類型:

  • 存儲型XSS:服務(wù)端對用戶輸入的惡意腳本沒有經(jīng)過驗證就存入數(shù)據(jù)庫,每次調(diào)用數(shù)據(jù)庫都會將其渲染在瀏覽器上。則可能為存儲型XSS。
  • 反射型XSS:通過get或者post等方式,向服務(wù)端輸入數(shù)據(jù)。如果服務(wù)端不進行過濾,驗證或編碼,直接將用戶信息呈現(xiàn)出來,可能會造成反射型XSS。

本文主要對SpringBoot2.x集成AntiSamy防御XSS攻擊進行簡單總結(jié),其中SpringBoot使用的2.4.5版本。

一、引入依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- AntiSamy依賴 -->
<dependency>
    <groupId>org.owasp.antisamy</groupId>
    <artifactId>antisamy</artifactId>
    <version>1.6.2</version>
</dependency>
<!-- lombok插件 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.8</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-text</artifactId>
    <version>1.9</version>
</dependency>

二、策略文件

Antisamy對惡意代碼的過濾依賴于策略文件,策略文件為xml格式,規(guī)定了AntiSamy對各個標簽、屬性的處理方法。策略文件定義的嚴格與否,決定了AntiSamy對Xss的防御效果。在AntiSamy的jar包中,已經(jīng)包含了幾個常用的策略文件:

1

本文使用antisamy-ebay.xml作為策略文件,該策略相對安全,適用于電商網(wǎng)站。將antisamy-ebay.xmlantisamy.xsd復(fù)制到resouces目錄下。對于策略文件的具體內(nèi)容這里不進行深入了解,只需了解下對標簽的處理規(guī)則<tag-rules>,共有remove、truncate、validate三種處理方式,其中remove為直接刪除,truncate為縮短標簽,只保留標簽和值,validate為驗證標簽屬性:

2

上圖截取了<tag-rules>的一部分,可知對script標簽的處理策略是remove。

三、實體類和Controller

用戶實體類:

package com.rtxtitanv.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author rtxtitanv
 * @version 1.0.0
 * @name com.rtxtitanv.model.User
 * @description 用戶實體類
 * @date 2021/8/23 14:54
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
    private Long id;
    private String username;
    private String password;
}

Controller:

package com.rtxtitanv.controller;

import com.rtxtitanv.model.User;
import org.springframework.web.bind.annotation.*;

/**
 * @author rtxtitanv
 * @version 1.0.0
 * @name com.rtxtitanv.controller.UserController
 * @description UserController
 * @date 2021/8/23 14:54
 */
@RequestMapping("/user")
@RestController
public class UserController {

    @PostMapping("/save")
    public User saveUser(User user) {
        return user;
    }

    @GetMapping("/get")
    public User getUserById(@RequestParam(value = "id") Long id) {
        return new User(id, "ZhaoYun", "123456");
    }

    @PutMapping("/update")
    public User updateUser(@RequestBody User user) {
        return user;
    }
}

四、創(chuàng)建過濾器

package com.rtxtitanv.filter;

import com.rtxtitanv.wrapper.XssRequestWrapper;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @author rtxtitanv
 * @version 1.0.0
 * @name com.rtxtitanv.filter.XssFilter
 * @description XSS過濾器
 * @date 2021/8/23 15:01
 */
public class XssFilter implements Filter {

    private FilterConfig filterConfig;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        // 攔截請求,處理XSS過濾
        chain.doFilter(new XssRequestWrapper((HttpServletRequest)request), response);
    }

    @Override
    public void destroy() {
        this.filterConfig = null;
    }
}

注意:在過濾器中并沒有直接對請求參數(shù)進行過濾清洗,而是在XssRequestWrapper類中進行的。XssRequestWrapper類將當(dāng)前的request對象進行了包裝,在過濾器放行時會自動調(diào)用XssRequestWrapper中的方法對請求參數(shù)進行清洗。

五、創(chuàng)建XssRequestWrapper類

package com.rtxtitanv.wrapper;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.owasp.validator.html.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Map;
import java.util.Objects;

/**
 * @author rtxtitanv
 * @version 1.0.0
 * @name com.rtxtitanv.wrapper.XssRequestWrapper
 * @description 裝飾器模式加強對request的處理,基于AntiSamy進行XSS防御
 * @date 2021/8/23 15:01
 */
public class XssRequestWrapper extends HttpServletRequestWrapper {

    private static final Logger LOGGER = LoggerFactory.getLogger(XssRequestWrapper.class);
    private static Policy policy = null;

    static {
        try {
            // 獲取策略文件路徑,策略文件需要放到項目的classpath下
            String antiSamyPath = Objects
                .requireNonNull(XssRequestWrapper.class.getClassLoader().getResource("antisamy-ebay.xml")).getFile();
            LOGGER.info(antiSamyPath);
            // 獲取的文件路徑中有空格時,空格會被替換為%20,在new一個File對象時會出現(xiàn)找不到路徑的錯誤
            // 對路徑進行解碼以解決該問題
            antiSamyPath = URLDecoder.decode(antiSamyPath, "utf-8");
            LOGGER.info(antiSamyPath);
            // 指定策略文件
            policy = Policy.getInstance(antiSamyPath);
        } catch (UnsupportedEncodingException | PolicyException e) {
            e.printStackTrace();
        }
    }

    public XssRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    /**
     * 過濾請求頭
     *
     * @param name 參數(shù)名
     * @return 參數(shù)值
     */
    @Override
    public String getHeader(String name) {
        String header = super.getHeader(name);
        // 如果Header為空,則直接返回,否則進行清洗
        return StringUtils.isBlank(header) ? header : xssClean(header);
    }

    /**
     * 過濾請求參數(shù)
     *
     * @param name 參數(shù)名
     * @return 參數(shù)值
     */
    @Override
    public String getParameter(String name) {
        String parameter = super.getParameter(name);
        // 如果Parameter為空,則直接返回,否則進行清洗
        return StringUtils.isBlank(parameter) ? parameter : xssClean(parameter);
    }

    /**
     * 過濾請求參數(shù)(一個參數(shù)可以有多個值)
     *
     * @param name 參數(shù)名
     * @return 參數(shù)值數(shù)組
     */
    @Override
    public String[] getParameterValues(String name) {
        String[] parameterValues = super.getParameterValues(name);
        if (parameterValues != null) {
            int length = parameterValues.length;
            String[] newParameterValues = new String[length];
            for (int i = 0; i < length; i++) {
                LOGGER.info("AntiSamy清理之前的參數(shù)值:" + parameterValues[i]);
                // 清洗參數(shù)
                newParameterValues[i] = xssClean(parameterValues[i]);
                LOGGER.info("AntiSamy清理之后的參數(shù)值:" + newParameterValues[i]);
            }
            return newParameterValues;
        }
        return super.getParameterValues(name);
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> requestMap = super.getParameterMap();
        requestMap.forEach((key, value) -> {
            for (int i = 0; i < value.length; i++) {
                LOGGER.info(value[i]);
                value[i] = xssClean(value[i]);
                LOGGER.info(value[i]);
            }
        });
        return requestMap;
    }

    /**
     * 使用AntiSamy清洗數(shù)據(jù)
     *
     * @param value 需要清洗的數(shù)據(jù)
     * @return 清洗后的數(shù)據(jù)
     */
    private String xssClean(String value) {
        try {
            AntiSamy antiSamy = new AntiSamy();
            // 使用AntiSamy清洗數(shù)據(jù)
            final CleanResults cleanResults = antiSamy.scan(value, policy);
            // 獲得安全的HTML輸出
            value = cleanResults.getCleanHTML();
            // 對轉(zhuǎn)義的HTML特殊字符(<、>、"等)進行反轉(zhuǎn)義,因為AntiSamy調(diào)用scan方法時會將特殊字符轉(zhuǎn)義
            return StringEscapeUtils.unescapeHtml4(value);
        } catch (ScanException | PolicyException e) {
            e.printStackTrace();
        }
        return value;
    }

    /**
     * 通過修改Json序列化的方式來完成Json格式的XSS過濾
     */
    public static class XssStringJsonSerializer extends JsonSerializer<String> {

        @Override
        public Class<String> handledType() {
            return String.class;
        }

        @Override
        public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            if (!StringUtils.isBlank(value)) {
                try {
                    AntiSamy antiSamy = new AntiSamy();
                    final CleanResults cleanResults = antiSamy.scan(value, XssRequestWrapper.policy);
                    gen.writeString(StringEscapeUtils.unescapeHtml4(cleanResults.getCleanHTML()));
                } catch (ScanException | PolicyException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

六、創(chuàng)建配置類

package com.rtxtitanv.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.rtxtitanv.filter.XssFilter;
import com.rtxtitanv.wrapper.XssRequestWrapper;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import javax.servlet.Filter;

/**
 * @author rtxtitanv
 * @version 1.0.0
 * @name com.rtxtitanv.config.AntiSamyConfig
 * @description AntiSamy配置類
 * @date 2021/8/23 15:05
 */
@Configuration
public class AntiSamyConfig {

    /**
     * 配置XSS過濾器
     *
     * @return FilterRegistrationBean
     */
    @Bean
    public FilterRegistrationBean<Filter> filterRegistrationBean() {
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(new XssFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setOrder(1);
        return filterRegistrationBean;
    }

    /**
     * 用于過濾Json類型數(shù)據(jù)的解析器
     *
     * @param builder Jackson2ObjectMapperBuilder
     * @return ObjectMapper
     */
    @Bean
    public ObjectMapper xssObjectMapper(Jackson2ObjectMapperBuilder builder) {
        // 創(chuàng)建解析器
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        // 注冊解析器
        SimpleModule simpleModule = new SimpleModule("XssStringJsonSerializer");
        simpleModule.addSerializer(new XssRequestWrapper.XssStringJsonSerializer());
        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }
}

七、測試

啟動項目,發(fā)送如下POST請求,請求地址為http://localhost:8080/user/save,可見表單參數(shù)中的<script>標簽內(nèi)容被成功過濾:

3

發(fā)送如下GET請求,請求地址為http://localhost:8080/user/get?id=1<script>alert("XSS");</script>0,可見Query參數(shù)中的<script>標簽內(nèi)容被成功過濾:

4

發(fā)送如下PUT請求,請求地址為http://localhost:8080/user/update,可見Json類型參數(shù)中的<script>標簽內(nèi)容被成功過濾:

5

代碼示例

Github:https://github.com/RtxTitanV/springboot-learning/tree/master/springboot2.x-learning/springboot-antisamy

Gitee:https://gitee.com/RtxTitanV/springboot-learning/tree/master/springboot2.x-learning/springboot-antisamy

到此這篇關(guān)于SpringBoot2.x 整合 AntiSamy防御XSS攻擊的簡單總結(jié)的文章就介紹到這了,更多相關(guān)SpringBoot2.x防御XSS攻擊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java算法之串的簡單處理

    Java算法之串的簡單處理

    今天小編就為大家分享一篇關(guān)于Java算法之串的簡單處理,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • 關(guān)于HashMap源碼解讀

    關(guān)于HashMap源碼解讀

    HashMap是基于哈希表的Map接口實現(xiàn),主要用于存儲鍵值對,它通過數(shù)組、鏈表和紅黑樹來實現(xiàn),解決了哈希沖突問題,Java?8中,HashMap對數(shù)據(jù)結(jié)構(gòu)進行了優(yōu)化,引入紅黑樹來提高查找效率,此外,HashMap是非線程安全的,適用于單線程環(huán)境
    2024-09-09
  • Java環(huán)境中MyBatis與Spring或Spring MVC框架的集成方法

    Java環(huán)境中MyBatis與Spring或Spring MVC框架的集成方法

    和MyBatis類似,Spring或者Spring MVC框架在Web應(yīng)用程序的運作中同樣主要負責(zé)處理數(shù)據(jù)庫事務(wù),這里我們就來看一下Java環(huán)境中MyBatis與Spring或Spring MVC框架的集成方法
    2016-06-06
  • Java 過濾器實現(xiàn)敏感詞匯過濾功能

    Java 過濾器實現(xiàn)敏感詞匯過濾功能

    通過使用 Java 過濾器,我們可以輕松地實現(xiàn)敏感詞匯過濾的功能,以保護用戶免受不良內(nèi)容的侵害,讓我們通過一個簡單的示例來演示我們的敏感詞匯過濾器是如何工作的,感興趣的朋友一起看看吧
    2024-01-01
  • springboot如何集成mysql

    springboot如何集成mysql

    這篇文章主要介紹了springboot如何集成mysql問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Springmvc restful配置遇到的小坑

    Springmvc restful配置遇到的小坑

    本文是小編給大家?guī)Я说腟pringmvc restful配置遇到的小小坑,小編給大家?guī)砹藛栴}原因及解決辦法,非常不錯,具有參考借鑒價值,感興趣的朋友一起看下吧
    2016-07-07
  • 使用MUI框架構(gòu)建App請求http接口實例代碼

    使用MUI框架構(gòu)建App請求http接口實例代碼

    下面小編就為大家分享一篇使用MUI框架構(gòu)建App請求http接口實例代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • 淺談解決Hibernate懶加載的4種方式

    淺談解決Hibernate懶加載的4種方式

    這篇文章主要介紹了淺談解決Hibernate懶加載的4種方式,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • Java并發(fā)程序入門介紹

    Java并發(fā)程序入門介紹

    這篇文章主要介紹了Java并發(fā)程序入門 ,需要的朋友可以參考下
    2015-03-03
  • JDK8時間相關(guān)類超詳細總結(jié)(含多個實例)

    JDK8時間相關(guān)類超詳細總結(jié)(含多個實例)

    jdk1.8的一些新特性簡化了代碼的寫法,減少了部分開發(fā)量,下面這篇文章主要給大家介紹了關(guān)于JDK8時間相關(guān)類超詳細總結(jié),文中包含了多個實例代碼,需要的朋友可以參考下
    2023-01-01

最新評論