亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

springboot項目如何防止XSS攻擊

 更新時間:2021年06月23日 08:53:23   作者:細肉云吞  
XSS攻擊全稱跨站腳本攻擊,是一種在web應用中的計算機安全漏洞,允許惡意web用戶將代碼植入到提供給其它用戶使用的頁面中。本文介紹防止XSS攻擊的方法

1. 什么是XSS攻擊?

    XSS攻擊全稱跨站腳本攻擊,是一種在web應用中的計算機安全漏洞,它允許惡意web用戶將代碼植入到提供給其它用戶使用的頁面中。也就是作惡的用戶通過表單提交一些前端代碼,如果不做處理的話,這些前端代碼將會在展示的時候被瀏覽器執(zhí)行。

2. 如何防范?

有兩種方式,一種是一些特殊字符轉(zhuǎn)義,另一種是去除一些危險html元素。本文通過JSOUP庫實現(xiàn)第二種方式。

現(xiàn)在問題是,在什么時候?qū)SS攻擊的字符串進行處理呢?這就涉及到spring mvc的Controller中的method params什么時候注入的問題。下面對方法參數(shù)注入的原理進行簡單說明。

2.1 什么時候注入請求參數(shù)

常見的控制器方法有下面幾種,分別是通過GET獲取請求參數(shù),POST獲取json或者form表單的參數(shù)

        /**
         * 通過url的path,獲取請求參數(shù)
         */
        @ResponseBody
        @GetMapping("/xssByGetUsingPath/{content}")
        public String testGetUsingPath(@PathVariable(name = "content") String content) {
            return content;
        }       


         /**
         * 通過url的query params獲取請求數(shù)據(jù). 方法使用簡單類型進行接收
         */
        @ResponseBody
        @GetMapping("/xssByGetUsingSimple")
        public String testUsingSimple(@RequestParam(name = "content") String content) {
            return content;
        }

        /**
         * 通過url的query params獲取請求數(shù)據(jù). 方法使用model進行接收
         */
        @ResponseBody
        @GetMapping("/xssByGetUsingModel")
        public String testGetUsingModel(BaseTest.Paper paper) {
            return paper.getContent();
        }

        /**
         * 通過 form 表單的方式獲取數(shù)據(jù). 方法使用簡單類型進行接收
         */
        @ResponseBody
        @PostMapping("/xssByFormPostUsingSimple")
        public String testFormPostUsingSimple(@RequestParam(name = "content") String content) {
            return content;
        }

        /**
         * 通過 form 表單的方式獲取數(shù)據(jù). 方法使用model進行參數(shù)接收
         */
        @ResponseBody
        @PostMapping("/xssByFormPostUsingModel")
        public String testFormPostUsingModel(BaseTest.Paper paper) {
            return paper.getContent();
        }

        /**
         * 通過 request body 發(fā)送 json數(shù)據(jù)
         */
        @ResponseBody
        @PostMapping("/xssByPostJsonBody")
        public String testPostJsonBody(@RequestBody BaseTest.Paper paper) {
            return paper.getContent();
        }

大家都知道,在spring mvc中處理請求的入口在 DispatcherServlet 類中,其中 doDispatch() 方法完成所有核心功能。在該主流程中,HandlerAdapter 將會對HTTP請求進行 Controller 的方法調(diào)用,以及對請求結(jié)果進行轉(zhuǎn)換,并封裝為DispatcherServlet 類需要的 ModelAndView 。在這里,由于使用注解的方式進行 Controller 定義,所以 HandlerAdapter 的實現(xiàn)類為 RequestMappingHandlerAdapter 。RequestMappingHandlerAdapter 類的 handle() 方法中,委托給 HandlerMethodArgumentResolver 對每個 Controller 的 方法的每個參數(shù)進行解析,反射調(diào)用 Controller 的 方法后,再 委托 HandlerMethodReturnValueHandler 對反射調(diào)用的返回值進行處理。

至此,本文的主角出現(xiàn)了,也就是 HandlerMethodArgumentResolver 。我們看下有關(guān)于本文的HandlerMethodArgumentResolver 類繼承關(guān)系。

上面的常見controller定義方法的 參數(shù)解析(注意,這里是說方法那里的參數(shù)解析) 對應 HandlerMethodArgumentResolver  的關(guān)系如下圖:

現(xiàn)在,我們已經(jīng)知道了他們都由什么樣 HandlerMethodArgumentResolver  解析方法參數(shù),我們繼續(xù)分析他們之前的共同點,并得到在哪里對http傳過來的數(shù)據(jù)進行XSS處理。

RequestResponseBodyMethodProcessor 是一個對request body的JSON數(shù)據(jù)反序列化的處理器,在 resolveArgument() 方法中,將會獲取合適的 org.springframework.http.converter.HttpMessageConverter  類對string數(shù)據(jù)進行反序列化處理。springboot 在初始化的時候,已經(jīng)默認注冊了 jackson 的 MappingJackson2HttpMessageConverter ,并使用它對 JSON 數(shù)據(jù)進行反序列化操作。在 jackson 里面,JsonDeserializer 類 用于json數(shù)據(jù)的property的反序列化,因此,我們可以通過擴展 JsonDeserializer ,并在里面處理XSS即可。

對于  PathVariableMethodArgumentResolver、 RequestParamMethodArgumentResolver、 ServletModelAttributeMethodProcessor ,在 resolveArgument() 方法中,他們對需要對請求參數(shù)調(diào)用 DataBinder 類 對獲取到的參數(shù)類型轉(zhuǎn)換和數(shù)據(jù)綁定。對于類型轉(zhuǎn)換的過程,他們會使用 org.springframework.core.convert.converter.Converter  進行轉(zhuǎn)換。同樣,在SPRINGBOOT初始化的過程,也注冊了很多個默認的轉(zhuǎn)換器,我們可以注冊一個自定義轉(zhuǎn)換器,用于對數(shù)據(jù)進行xss處理。

3. 具體處理細節(jié)

抽象XSSCleaner,用于對string進行XSS處理

public interface XssCleaner {

    /**
     * 清理 html, 防止XSS
	 *
     * @param html html
     * @return 清理后的數(shù)據(jù)
     */
    String clean(String html);

}

使用JSOUP,做HTML節(jié)點的白名單處理

public class DefaultXssCleaner implements XssCleaner {

    public static final HtmlWhitelist WHITE_LIST = new HtmlWhitelist();

    @Override
    public String clean(String html) {
        if (StringUtils.hasText(html)) {
            return Jsoup.clean(html, WHITE_LIST);
        }
        return html;
    }

    private static class HtmlWhitelist extends Whitelist {

        public HtmlWhitelist() {
            //定義標簽和屬性的白名單

            addTags("a", "b", "blockquote", "br", "caption", "cite", "code", "col", "colgroup", "dd", "div", "span", "embed", "object", "dl", "dt",
                    "em", "h1", "h2", "h3", "h4", "h5", "h6", "i", "img", "li", "ol", "p", "pre", "q", "small",
                    "strike", "strong", "sub", "sup", "table", "tbody", "td", "tfoot", "th", "thead", "tr", "u", "ul");

            addAttributes("a", "href", "title", "target");
            addAttributes("blockquote", "cite");
            addAttributes("col", "span");
            addAttributes("colgroup", "span");
            addAttributes("img", "align", "alt", "src", "title");
            addAttributes("ol", "start");
            addAttributes("q", "cite");
            addAttributes("table", "summary");
            addAttributes("td", "abbr", "axis", "colspan", "rowspan", "width");
            addAttributes("th", "abbr", "axis", "colspan", "rowspan", "scope", "width");
            addAttributes("video", "src", "autoplay", "controls", "loop", "muted", "poster", "preload");
            addAttributes("object", "width", "height", "classid", "codebase");
            addAttributes("param", "name", "value");
            addAttributes("embed", "src", "quality", "width", "height", "allowFullScreen", "allowScriptAccess", "flashvars", "name", "type", "pluginspage");

            addAttributes(":all", "class", "style", "height", "width", "type", "id", "name");

            addProtocols("blockquote", "cite", "http", "https");
            addProtocols("cite", "cite", "http", "https");
            addProtocols("q", "cite", "http", "https");

        }

        @Override
        protected boolean isSafeAttribute(String tagName, Element el, Attribute attr) {
            //不允許 javascript 開頭的 src 和 href
            if ("src".equalsIgnoreCase(attr.getKey()) || "href".equalsIgnoreCase(attr.getKey())) {
                String value = attr.getValue();
                if (StringUtils.hasText(value) && value.toLowerCase().startsWith("javascript")) {
                    return false;
                }
            }

            //允許 base64 的圖片內(nèi)容
            if ("img".equals(tagName) && "src".equals(attr.getKey()) && attr.getValue().startsWith("data:;base64")) {
                return true;
            }

            return super.isSafeAttribute(tagName, el, attr);
        }
    }
}

新增一個jackson的JsonDeserializer 

/**
 * jackson的反序列化時的html xss過濾器
 */
public class JacksonXssCleanJsonDeserializer extends JsonDeserializer<String> {

    private final static Logger LOGGER = LoggerFactory.getLogger(JacksonXssCleanJsonDeserializer.class);

    private final XssCleaner xssCleaner;

    public JacksonXssCleanJsonDeserializer(XssCleaner xssCleaner) {
        this.xssCleaner = xssCleaner;
    }

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

    @Override
    public String deserialize(JsonParser p, DeserializationContext context) throws IOException, JsonProcessingException {
        // XSS clean
        String text = p.getValueAsString();
        if (StringUtils.hasText(text) && XssCleanMarker.shouldClean()) {
            String cleanText = xssCleaner.clean(text);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Json property value: [{}] cleaned up by JacksonXssCleanJsonDeserializer, current value is:{}.", text, cleanText);
            }
            return cleanText;
        }
        return text;
    }
}

新增 Converter 

/**
 * 對請求數(shù)據(jù)過濾xss
 */
public class XssCleanConverter implements Converter<String, String> {

    private final Logger LOGGER = LoggerFactory.getLogger(XssCleanConverter.class);

    private XssCleaner xssCleaner;

    public XssCleanConverter(XssCleaner xssCleaner) {
        this.xssCleaner = xssCleaner;
    }

    @Override
    public String convert(String text) {
        if (StringUtils.hasText(text) && XssCleanMarker.shouldClean()) {
            String cleanText = xssCleaner.clean(text);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("request param [{}] cleaned up by XssCleanConverter, current value is:{}.", text, cleanText);
            }
            return cleanText;
        }
        return text;
    }
}

對 JsonDeserializer  和 Converter 進行注冊

@Configuration
@ConditionalOnProperty(value = XSS_PROPERTIES_ENABLED, havingValue = "true", matchIfMissing = true)
@ConditionalOnWebApplication
@EnableConfigurationProperties({XssProperties.class})
public class WebXssConfiguration implements WebMvcConfigurer {

    private XssProperties properties;

    public WebXssConfiguration(XssProperties properties) {
        this.properties = properties;
    }

    @Bean
    @ConditionalOnMissingBean
    public XssCleaner xssCleaner() {
        return new DefaultXssCleaner();
    }

    @Bean
    @ConditionalOnClass(value = {ObjectMapper.class, Jackson2ObjectMapperBuilder.class})
    public Jackson2ObjectMapperBuilderCustomizer jacksonXssCleanJsonDeserializerCustomer(XssCleaner xssCleaner) {
        return builder -> builder.deserializers(new JacksonXssCleanJsonDeserializer(xssCleaner));
    }

    @Override
    public void addFormatters(FormatterRegistry registry) {
        XssCleaner xssCleaner = xssCleaner();
        registry.addConverter(new XssCleanConverter(xssCleaner));
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        XssCleanMarkerHandlerInterceptor handlerInterceptor = new XssCleanMarkerHandlerInterceptor(properties);
        registry.addInterceptor(handlerInterceptor);
    }
}

上面是XSS處理的核心代碼。處理XSS處理,還進行了一些擴展,比如 http path 路徑的過濾 和 一些使能控制。

完整的代碼可以參考倉庫:倉庫地址

以上就是springboot項目如何防止XSS攻擊的詳細內(nèi)容,更多關(guān)于springboot防止XSS攻擊的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java生成隨機數(shù)之Random與ThreadLocalRandom性能比較詳解

    Java生成隨機數(shù)之Random與ThreadLocalRandom性能比較詳解

    大家項目中如果有生成隨機數(shù)的需求,我想大多都會選擇使用Random來實現(xiàn),它內(nèi)部使用了CAS來實現(xiàn)。?實際上,JDK1.7之后,提供了另外一個生成隨機數(shù)的類ThreadLocalRandom,那么他們二者之間的性能是怎么樣的呢?本文就來詳細說說
    2022-12-12
  • SpringBoot擴展SpringMVC原理并實現(xiàn)全面接管

    SpringBoot擴展SpringMVC原理并實現(xiàn)全面接管

    這篇文章主要介紹了SpringBoot擴展SpringMVC原理并實現(xiàn)全面接管,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • 關(guān)于弗洛伊德算法求最短路徑詳解

    關(guān)于弗洛伊德算法求最短路徑詳解

    這篇文章主要介紹了關(guān)于弗洛伊德算法求最短路徑詳解,弗洛伊德算法VS迪杰斯特拉算法:迪杰斯特拉算法通過選定的被訪問頂點,求出從出發(fā)訪問頂點到其他項點的最短路徑:弗洛伊德算法中每-個頂點都是出發(fā)訪問點,需要的朋友可以參考下
    2023-07-07
  • Java連接mysql數(shù)據(jù)庫的詳細教程(推薦)

    Java連接mysql數(shù)據(jù)庫的詳細教程(推薦)

    這篇文章主要介紹了Java連接mysql數(shù)據(jù)庫的詳細教程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • 一文掌握Java中List和Set接口的基本使用

    一文掌握Java中List和Set接口的基本使用

    這篇文章主要為大家詳細介紹Java中List和Set接口,文中通過示例代碼讓大家能夠輕松掌握List和Set接口的基本使用,感興趣的可以跟隨小編一起學習一下
    2022-07-07
  • Maven中plugins和pluginManagement區(qū)別小結(jié)

    Maven中plugins和pluginManagement區(qū)別小結(jié)

    pluginManagement是表示插件聲明,plugins就是直接引入一個plugin,本文主要介紹了Maven中plugins和pluginManagement區(qū)別小結(jié),具有一定的參考價值,感興趣的可以了解一下
    2024-06-06
  • 詳解Spring Cloud微服務(wù)架構(gòu)下的WebSocket解決方案

    詳解Spring Cloud微服務(wù)架構(gòu)下的WebSocket解決方案

    這篇文章主要介紹了詳解Spring Cloud微服務(wù)架構(gòu)下的WebSocket解決方案,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • Spring源碼解析容器初始化構(gòu)造方法

    Spring源碼解析容器初始化構(gòu)造方法

    這篇文章主要介紹了Spring源碼解析容器初始化構(gòu)造方法,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-07-07
  • Java9新特性Module模塊化編程示例演繹

    Java9新特性Module模塊化編程示例演繹

    這篇文章主要為大家介紹了Java9新特性Module模塊化編程的示例演繹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2022-03-03
  • java讀寫excel文件實現(xiàn)POI解析Excel的方法

    java讀寫excel文件實現(xiàn)POI解析Excel的方法

    在日常工作中,我們常常會進行Excel文件讀寫操作,這篇文章主要介紹了java讀寫excel文件實現(xiàn)POI解析Excel的方法,實例分析了java讀寫excel的技巧,非常具有實用價值,需要的朋友可以參考下
    2018-10-10

最新評論