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

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

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

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

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

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

本文主要對(duì)SpringBoot2.x集成AntiSamy防御XSS攻擊進(jìn)行簡(jiǎn)單總結(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對(duì)惡意代碼的過濾依賴于策略文件,策略文件為xml格式,規(guī)定了AntiSamy對(duì)各個(gè)標(biāo)簽、屬性的處理方法。策略文件定義的嚴(yán)格與否,決定了AntiSamy對(duì)Xss的防御效果。在AntiSamy的jar包中,已經(jīng)包含了幾個(gè)常用的策略文件:

1

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

2

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

三、實(shí)體類和Controller

用戶實(shí)體類:

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 用戶實(shí)體類
 * @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 {
        // 攔截請(qǐng)求,處理XSS過濾
        chain.doFilter(new XssRequestWrapper((HttpServletRequest)request), response);
    }

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

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

五、創(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 裝飾器模式加強(qiáng)對(duì)request的處理,基于AntiSamy進(jìn)行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 {
            // 獲取策略文件路徑,策略文件需要放到項(xiàng)目的classpath下
            String antiSamyPath = Objects
                .requireNonNull(XssRequestWrapper.class.getClassLoader().getResource("antisamy-ebay.xml")).getFile();
            LOGGER.info(antiSamyPath);
            // 獲取的文件路徑中有空格時(shí),空格會(huì)被替換為%20,在new一個(gè)File對(duì)象時(shí)會(huì)出現(xiàn)找不到路徑的錯(cuò)誤
            // 對(duì)路徑進(jì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);
    }

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

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

    /**
     * 過濾請(qǐng)求參數(shù)(一個(gè)參數(shù)可以有多個(gè)值)
     *
     * @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();
            // 對(duì)轉(zhuǎn)義的HTML特殊字符(<、>、"等)進(jìn)行反轉(zhuǎn)義,因?yàn)锳ntiSamy調(diào)用scan方法時(shí)會(huì)將特殊字符轉(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();
        // 注冊(cè)解析器
        SimpleModule simpleModule = new SimpleModule("XssStringJsonSerializer");
        simpleModule.addSerializer(new XssRequestWrapper.XssStringJsonSerializer());
        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }
}

七、測(cè)試

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

3

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

4

發(fā)送如下PUT請(qǐng)求,請(qǐng)求地址為http://localhost:8080/user/update,可見Json類型參數(shù)中的<script>標(biāo)簽內(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ǎn)單總結(jié)的文章就介紹到這了,更多相關(guān)SpringBoot2.x防御XSS攻擊內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決spring boot2集成activiti6踩過的坑

    解決spring boot2集成activiti6踩過的坑

    這篇文章主要介紹了解決spring boot2集成activiti6踩過的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 簡(jiǎn)單聊聊RabbitMQ中的隊(duì)頭阻塞問題

    簡(jiǎn)單聊聊RabbitMQ中的隊(duì)頭阻塞問題

    這篇文章主要為大家詳細(xì)介紹了RabbitMQ中的隊(duì)頭阻塞問題以及相關(guān)的解決方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-02-02
  • 詳解Java虛擬機(jī)(JVM)運(yùn)行時(shí)

    詳解Java虛擬機(jī)(JVM)運(yùn)行時(shí)

    JVM(Java虛擬機(jī))是一個(gè)抽象的計(jì)算模型。這篇文章主要介紹了Java虛擬機(jī)(JVM)運(yùn)行時(shí)的相關(guān)知識(shí),需要的朋友可以參考下
    2018-10-10
  • 淺談Spring Bean的作用域之間有什么區(qū)別

    淺談Spring Bean的作用域之間有什么區(qū)別

    Spring的bean有5種作用域是singleton、prototype、request、session和globalSession,本文主要介紹了淺談Spring Bean的作用域之間有什么區(qū)別,感興趣的可以了解一下
    2024-05-05
  • java list 比較詳解及實(shí)例

    java list 比較詳解及實(shí)例

    這篇文章主要介紹了java list 比較詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • 利用java開發(fā)簡(jiǎn)易版掃雷游戲

    利用java開發(fā)簡(jiǎn)易版掃雷游戲

    這篇文章主要介紹了利用java開發(fā)一個(gè)丐版掃雷游戲,喜歡玩掃雷的小伙伴們一定要試試哦,對(duì)正在學(xué)習(xí)java開發(fā)的小伙伴們也有一定幫助,需要的朋友可以參考下
    2021-04-04
  • java垃圾收集器與內(nèi)存分配策略詳解

    java垃圾收集器與內(nèi)存分配策略詳解

    本篇文章主要介紹了Java垃圾收集器與內(nèi)存分配策略的方法和原理總結(jié),Java垃圾回收器是Java虛擬機(jī)的重要模塊,具有一定的參考價(jià)值,有興趣的可以了解一下
    2021-08-08
  • Java中的static關(guān)鍵字用法總結(jié)

    Java中的static關(guān)鍵字用法總結(jié)

    這篇文章主要介紹了Java中的static關(guān)鍵字用法總結(jié),static是Java50個(gè)關(guān)鍵字之一,static關(guān)鍵字可以用來修飾代碼塊表示靜態(tài)代碼塊,修飾成員變量表示全局靜態(tài)成員變量,修飾方法表示靜態(tài)方法,需要的朋友可以參考下
    2023-11-11
  • spring boot如何基于JWT實(shí)現(xiàn)單點(diǎn)登錄詳解

    spring boot如何基于JWT實(shí)現(xiàn)單點(diǎn)登錄詳解

    這篇文章主要介紹了spring boot如何基于JWT實(shí)現(xiàn)單點(diǎn)登錄詳解,用戶只需登錄一次就能夠在這兩個(gè)系統(tǒng)中進(jìn)行操作。很明顯這就是單點(diǎn)登錄(Single Sign-On)達(dá)到的效果,需要的朋友可以參考下
    2019-06-06
  • java中fork-join的原理解析

    java中fork-join的原理解析

    Fork/Join框架是Java7提供用于并行執(zhí)行任務(wù)的框架,是一個(gè)把大任務(wù)分割成若干個(gè)小任務(wù),今天通過本文給大家分享java中fork join原理,感興趣的朋友一起看看吧
    2021-04-04

最新評(píng)論

库车县| 五华县| 延庆县| 榕江县| 山阴县| 大连市| 嘉定区| 政和县| 栖霞市| 彩票| 泰宁县| 衡东县| 陇川县| 天全县| 封开县| 嵩明县| 贵港市| 延川县| 前郭尔| 三台县| 胶南市| 涞水县| 元阳县| 江华| 云梦县| 武宣县| 金堂县| 中阳县| 华蓥市| 根河市| 图木舒克市| 尚志市| 新竹县| 南平市| 陕西省| 张掖市| 大足县| 金平| 金阳县| 花莲县| 双鸭山市|