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

SpringBoot如何使用過濾器進行XSS防御

 更新時間:2024年11月15日 15:54:35   作者:morris131  
想對全局的請求都進行XSS防御可以使用servlet中的過濾器或者spring mvc中的攔截器,下面我們就來看看如何使用servlet中的過濾器進行XSS防御吧

在Spring Boot中,我們可以使用注解的方式來進行XSS防御。注解是一種輕量級的防御手段,它可以在方法或字段級別對輸入進行校驗,從而防止XSS攻擊。

而想對全局的請求都進行XSS防御可以使用servlet中的過濾器或者spring mvc中的攔截器,這里使用servlet中的過濾器進行演示。

引入相關(guān)依賴

maven依賴:

<!--JSR-303/JSR-380用于驗證的注解 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    <version>2.6.7</version>
</dependency>

如果是使用grade,引入依賴:

implementation 'org.springframework.boot:spring-boot-starter-validation:2.6.7'

修改配置文件

xss:
  enabled: true
  excludeUrlList:
    - /xss/local/test

定義配置文件對應(yīng)的屬性類

package com.morris.spring.boot.module.xss;

import lombok.Data;

import java.util.List;

@Data
public class XssFilterProperties {
    /**
     * 是否啟用XSS過濾。
     */
    private boolean enabled = true;

    /**
     * 需要排除的URL模式,這些URL不會進行XSS過濾。
     */
    private List<String> excludeUrlList;
}

注入XSS配置類

package com.morris.spring.boot.module.xss;

import lombok.Data;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;

import javax.servlet.DispatcherType;

@Data
@Configuration
public class XssFilterConfig {

    @ConfigurationProperties(prefix = "xss")
    @Bean
    public XssFilterProperties xssFilterProperties() {
        return new XssFilterProperties();
    }

    /**
     * 注冊XSS過濾器。
     *
     * @return FilterRegistrationBean 用于注冊過濾器的bean。
     */
    @Bean
    public FilterRegistrationBean<XssFilter> xssFilterRegistration(XssFilterProperties xssFilterProperties) {
        FilterRegistrationBean<XssFilter> registrationBean = new FilterRegistrationBean<>();
        // 設(shè)置過濾器的分發(fā)類型為請求類型
        registrationBean.setDispatcherTypes(DispatcherType.REQUEST);
        // 創(chuàng)建XssFilter的實例
        registrationBean.setFilter(new XssFilter(xssFilterProperties));
        // 添加過濾器需要攔截的URL模式,這里攔截所有請求
        registrationBean.addUrlPatterns("/*");
        // 設(shè)置過濾器的名稱
        registrationBean.setName("XssFilter");
        // 設(shè)置過濾器的執(zhí)行順序,數(shù)值越小,優(yōu)先級越高
        registrationBean.setOrder(9999);
        return registrationBean;
    }

    @Bean
    public HttpMessageConverters xssHttpMessageConverters() {
        XSSMappingJackson2HttpMessageConverter xssMappingJackson2HttpMessageConverter = new XSSMappingJackson2HttpMessageConverter();
        HttpMessageConverter converter = xssMappingJackson2HttpMessageConverter;
        return new HttpMessageConverters(converter);
    }

}

XssFilter過濾器

XssFilter過濾器會將所有需要進行防御的請求包裝為XssWrapper。

package com.morris.spring.boot.module.xss;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class XssFilter implements Filter {

    private final XssFilterProperties xssFilterProperties;

    public XssFilter(XssFilterProperties xssFilterProperties) {
        this.xssFilterProperties = xssFilterProperties;
    }

    /**
     * 執(zhí)行過濾邏輯,如果當(dāng)前請求不在排除列表中,則通過XSS過濾器包裝請求。
     *
     * @param request  HTTP請求對象。
     * @param response HTTP響應(yīng)對象。
     * @param chain    過濾器鏈對象,用于繼續(xù)或中斷請求處理。
     * @throws IOException      如果處理過程中出現(xiàn)I/O錯誤。
     * @throws ServletException 如果處理過程中出現(xiàn)Servlet相關(guān)錯誤。
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        //如果該訪問接口在排除列表里面則不攔截
        if (isExcludeUrl(req.getServletPath())) {
            chain.doFilter(request, response);
            return;
        }

        log.info("uri:{}", req.getRequestURI());
        // xss 過濾
        chain.doFilter(new XssWrapper(req), resp);
    }

    /**
     * 判斷當(dāng)前請求的URL是否應(yīng)該被排除在XSS過濾之外。
     *
     * @param urlPath 請求的URL路徑。
     * @return 如果請求應(yīng)該被排除,則返回true;否則返回false。
     */
    private boolean isExcludeUrl(String urlPath) {
        if (!xssFilterProperties.isEnabled()) {
            //如果xss開關(guān)關(guān)閉了,則所有url都不攔截
            return true;
        }

        if(CollectionUtils.isEmpty(xssFilterProperties.getExcludeUrlList())) {
            return false;
        }

        for (String pattern : xssFilterProperties.getExcludeUrlList()) {
            Pattern p = Pattern.compile("^" + pattern);
            Matcher m = p.matcher(urlPath);
            if (m.find()) {
                return true;
            }
        }
        return false;
    }
}

XssWrapper過濾get請求和請求頭

XssWrapper會過濾get請求和請求頭中的非法字符。

package com.morris.spring.boot.module.xss;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

@Slf4j
public class XssWrapper extends HttpServletRequestWrapper {

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

    /**
     * 對數(shù)組參數(shù)進行特殊字符過濾
     */
    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);
        if (values == null) {
            return null;
        }
        int count = values.length;
        String[] encodedValues = new String[count];
        for (int i = 0; i < count; i++) {
            encodedValues[i] = XssUtil.clean(values[i]);
        }
        return encodedValues;
    }

    /**
     * 對參數(shù)中特殊字符進行過濾
     */
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (StringUtils.isBlank(value)) {
            return value;
        }
        return XssUtil.clean(value);
    }

    /**
     * 獲取attribute,特殊字符過濾
     */
    @Override
    public Object getAttribute(String name) {
        Object value = super.getAttribute(name);
        if (value instanceof String && StringUtils.isNotBlank((String) value)) {
            return XssUtil.clean((String) value);
        }
        return value;
    }

    /**
     * 對請求頭部進行特殊字符過濾
     */
    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        if (StringUtils.isBlank(value)) {
            return value;
        }
        return XssUtil.clean(value);
    }
}

MessageConverter過濾post請求

package com.morris.spring.boot.module.xss;

import com.fasterxml.jackson.databind.JavaType;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import java.io.IOException;
import java.lang.reflect.Type;

/**
 * 在讀取和寫入JSON數(shù)據(jù)時特殊字符避免xss攻擊的消息解析器
 *
 */
public class XSSMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {

    /**
     * 從HTTP輸入消息中讀取對象,同時應(yīng)用XSS防護。
     * 
     * @param type        類型令牌,表示要讀取的對象類型。
     * @param contextClass    上下文類,提供類型解析的上下文信息。
     * @param inputMessage HTTP輸入消息,包含要讀取的JSON數(shù)據(jù)。
     * @return 從輸入消息中解析出的對象,經(jīng)過XSS防護處理。
     * @throws IOException 如果發(fā)生I/O錯誤。
     * @throws HttpMessageNotReadableException 如果消息無法讀取。
     */
    @Override
    public Object read(Type type, Class contextClass,
                       HttpInputMessage inputMessage) throws IOException,
            HttpMessageNotReadableException {
        JavaType javaType = getJavaType(type, contextClass);
        Object obj = readJavaType(javaType, inputMessage);
        //得到請求json
        String json = super.getObjectMapper().writeValueAsString(obj);
        //過濾特殊字符
        String result = XssUtil.clean(json);
        Object resultObj = super.getObjectMapper().readValue(result, javaType);
        return resultObj;
    }

    /**
     * 從HTTP輸入消息中讀取指定Java類型的對象,內(nèi)部使用。
     * 
     * @param javaType    要讀取的對象的Java類型。
     * @param inputMessage HTTP輸入消息,包含要讀取的JSON數(shù)據(jù)。
     * @return 從輸入消息中解析出的對象。
     * @throws IOException 如果發(fā)生I/O錯誤。
     * @throws HttpMessageNotReadableException 如果消息無法讀取。
     */
    private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) {
        try {
            return super.getObjectMapper().readValue(inputMessage.getBody(), javaType);
        } catch (IOException ex) {
            throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
        }
    }

    /**
     * 將對象寫入HTTP輸出消息,同時應(yīng)用XSS防護。
     * 
     * @param object 要寫入的對象。
     * @param outputMessage HTTP輸出消息,對象將被序列化為JSON并寫入此消息。
     * @throws IOException 如果發(fā)生I/O錯誤。
     * @throws HttpMessageNotWritableException 如果消息無法寫入。
     */
    @Override
    protected void writeInternal(Object object, HttpOutputMessage outputMessage)
            throws IOException, HttpMessageNotWritableException {
        //得到要輸出的json
        String json = super.getObjectMapper().writeValueAsString(object);
        //過濾特殊字符
        String result = XssUtil.clean(json);
        // 輸出
        outputMessage.getBody().write(result.getBytes());
    }
}

Xss過濾工具類

package com.morris.spring.boot.module.xss;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Whitelist;

/**
 * XSS過濾工具類,使用Jsoup庫對輸入的字符串進行XSS攻擊防護
 */
public class XssUtil {

    /**
     * 使用jsoup自帶的relaxed白名單
     */
    private static final Whitelist WHITE_LIST = Whitelist.relaxed();
    /**
     * 定義輸出設(shè)置,關(guān)閉prettyPrint(prettyPrint=false),目的是避免在清理過程中對代碼進行格式化
     * 從而保持輸入和輸出內(nèi)容的一致性。
     */
    private static final Document.OutputSettings OUTPUT_SETTINGS = new Document.OutputSettings().prettyPrint(false);

    /*
      初始化白名單策略,允許所有標(biāo)簽擁有style屬性。
      這是因為在富文本編輯中,樣式通常通過style屬性來定義,需要確保這些樣式能夠被保留。
     */
    static {
        // 富文本編輯時一些樣式是使用 style 來進行實現(xiàn)的
        // 比如紅色字體 style="color:red;"
        // 所以需要給所有標(biāo)簽添加 style 屬性
        WHITE_LIST.addAttributes(":all", "style");
    }

    /**
     * 清理輸入的字符串,移除潛在的XSS攻擊代碼。
     *
     * @param content 待清理的字符串,通常是用戶輸入的HTML內(nèi)容。
     * @return 清理后的字符串,保證不包含XSS攻擊代碼。
     */
    public static String clean(String content) {
        // 使用定義好的白名單策略和輸出設(shè)置清理輸入的字符串
        return Jsoup.clean(content, "", WHITE_LIST, OUTPUT_SETTINGS);
    }
}

get請求測試

package com.morris.spring.boot.module.xss;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


/**
 * Xss2防御get請求
 */
@RestController
@RequestMapping("/xss/global")
@Validated
public class XssGlobalGetController {

    /**
     * 使用注解攔截get請求中的xss,在方法參數(shù)前面加上@Xss,注意類上面要加上@Validated注解
     *
     * @param userAccount 請求參數(shù)
     * @return 請求參數(shù)
     */
    @GetMapping("/test")
    public String test(String userAccount) {
        return userAccount;
    }

}

發(fā)送get請求:http://localhost:8888/xss/global/test?userAccount=demoData

返回結(jié)果:demoData

post請求測試

package com.morris.spring.boot.module.xss;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Xss全局防御post請求
 */
@RestController
@RequestMapping("/xss/global")
public class XssGlobalPostController {

    /**
     * 使用注解攔截POST請求中的xss,在實體類需要攔截xss的屬性上面加上@Xss或者@Validated注解
     *
     * @param userGlobalLoginPojo 實體類
     * @return 實體類
     */
    @PostMapping("/test")
    public UserGlobalLoginPojo test(@RequestBody UserGlobalLoginPojo userGlobalLoginPojo) {
        return userGlobalLoginPojo;
    }

}

發(fā)送post請求:http://localhost:8888/xss/global/test

請求體:

{
    "userAccount": "<iframe οnlοad='alert(0)'>demoData</iframe>"
}

返回結(jié)果:

{
    "userAccount": "demoData"
}

到此這篇關(guān)于SpringBoot如何使用過濾器進行XSS防御的文章就介紹到這了,更多相關(guān)SpringBoot XSS防御內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java?深入理解創(chuàng)建型設(shè)計模式之原型模式

    Java?深入理解創(chuàng)建型設(shè)計模式之原型模式

    原型(Prototype)模式的定義如下:用一個已經(jīng)創(chuàng)建的實例作為原型,通過復(fù)制該原型對象來創(chuàng)建一個和原型相同或相似的新對象。在這里,原型實例指定了要創(chuàng)建的對象的種類。用這種方式創(chuàng)建對象非常高效,根本無須知道對象創(chuàng)建的細節(jié)
    2022-02-02
  • spring@value注入配置文件值失敗的原因分析

    spring@value注入配置文件值失敗的原因分析

    這篇文章主要介紹了spring@value注入配置文件值失敗的原因分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 詳解Java中final的用法

    詳解Java中final的用法

    本文主要介紹了Java中final的使用方法,final是java的關(guān)鍵字,本文就詳細說明一下它的使用方法,需要的朋友可以參考下
    2015-08-08
  • Java并發(fā)編程之Semaphore(信號量)詳解及實例

    Java并發(fā)編程之Semaphore(信號量)詳解及實例

    這篇文章主要介紹了Java并發(fā)編程之Semaphore(信號量)詳解及實例的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Java程序連接數(shù)據(jù)庫的常用的類和接口介紹

    Java程序連接數(shù)據(jù)庫的常用的類和接口介紹

    這篇文章主要介紹了Java程序連接數(shù)據(jù)庫的常用的類和接口,包括Connection類和Statement類等,需要的朋友可以參考下
    2015-10-10
  • SpringBoot外部化配置使用Plus版的方法示例

    SpringBoot外部化配置使用Plus版的方法示例

    這篇文章主要介紹了SpringBoot外部化配置使用Plus版的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Java中ArrayList的常見用法示例小結(jié)

    Java中ArrayList的常見用法示例小結(jié)

    本文介紹了Java的ArrayList,它是一個動態(tài)數(shù)組,可以自動調(diào)整大小,支持添加、刪除、獲取元素等操作,同時,還討論了如何存儲基本數(shù)據(jù)類型以及在多線程環(huán)境下的使用注意事項,感興趣的朋友一起看看吧
    2025-02-02
  • IDEA在創(chuàng)建包時如何把包分開實現(xiàn)自動分層(方法詳解)

    IDEA在創(chuàng)建包時如何把包分開實現(xiàn)自動分層(方法詳解)

    這篇文章主要介紹了IDEA在創(chuàng)建包時如何把包分開實現(xiàn)自動分層,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-09-09
  • Java壓縮文件ZIP實例代碼

    Java壓縮文件ZIP實例代碼

    這篇文章主要介紹了Java壓縮文件ZIP實例代碼,有需要的朋友可以參考一下
    2013-12-12
  • java+vue實現(xiàn)添加單選題、多選題到題庫功能

    java+vue實現(xiàn)添加單選題、多選題到題庫功能

    這篇文章主要為大家詳細介紹了java+vue實現(xiàn)添加單選題、多選題到題庫功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04

最新評論