自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

發(fā)現(xiàn) XSS 漏洞?別急,用這招 SpringBoot 3.3 技巧輕松搞定!

開發(fā) 前端
我們創(chuàng)建了一個包含完整 XSS 防護(hù)的 Spring Boot 應(yīng)用。自定義注解、過濾器和參數(shù)解析器的結(jié)合使我們的解決方案靈活且易于擴(kuò)展。此方案不僅能有效防止 XSS 攻擊,還能保證應(yīng)用的可維護(hù)性和代碼的整潔度。

在 Web 開發(fā)中,XSS(跨站腳本攻擊)是一類常見且危險的漏洞。本文將介紹如何在 Spring Boot 3.3 項(xiàng)目中使用自定義注解和過濾器來防止 XSS 攻擊,并結(jié)合前端使用 Thymeleaf 模板引擎、JavaScript 及 Bootstrap 實(shí)現(xiàn)完整的防護(hù)方案。首先,讓我們了解一下 XSS 攻擊的類型、原理及示例。

XSS 攻擊類型及原理

XSS 攻擊可以分為以下三類:

  1. 存儲型 XSS(Stored XSS):攻擊者將惡意腳本存儲在目標(biāo)服務(wù)器上。例如,通過提交帶有惡意腳本的表單,服務(wù)器在后續(xù)響應(yīng)中將其返回給客戶端并執(zhí)行。
  2. 反射型 XSS(Reflected XSS):惡意腳本作為請求的一部分被發(fā)送到服務(wù)器,然后在響應(yīng)中返回并執(zhí)行。這種攻擊通常通過帶有惡意腳本的 URL 來實(shí)現(xiàn)。
  3. DOM 型 XSS(DOM-based XSS):攻擊者通過修改網(wǎng)頁的 DOM 環(huán)境(例如 JavaScript 操作 DOM)來執(zhí)行惡意腳本。這種攻擊利用的是客戶端環(huán)境而非服務(wù)器。

運(yùn)行效果:

圖片圖片

若想獲取項(xiàng)目完整代碼以及其他文章的項(xiàng)目源碼,且在代碼編寫時遇到問題需要咨詢交流,歡迎加入下方的知識星球。

攻擊示例

存儲型 XSS 示例:

<form action="/submit" method="post">
       <input type="text" name="comment" value="<script>alert('XSS');</script>">
       <button type="submit">Submit</button>
   </form>

反射型 XSS 示例:

http://example.com/search?query=<script>alert('XSS');</script>

DOM 型 XSS 示例:

<div id="content"></div>
   <script>
       var unsafeContent = '<script>alert("XSS");<\/script>';
       document.getElementById('content').innerHTML = unsafeContent;
   </script>

這些攻擊利用了網(wǎng)頁對用戶輸入缺乏適當(dāng)?shù)尿?yàn)證和過濾,從而使得惡意代碼得以執(zhí)行。接下來,本文將介紹如何在 SpringBoot 項(xiàng)目中實(shí)現(xiàn) XSS 防護(hù)。

項(xiàng)目配置

首先,我們創(chuàng)建一個 Spring Boot 項(xiàng)目。這里是項(xiàng)目的基本結(jié)構(gòu)和配置:

項(xiàng)目結(jié)構(gòu):

src
├── main
│   ├── java
│   │   └── com
│   │       └── icoderoad
│   │           └── xss_protection
│   │               ├── XssProtectionApplication.java
│   │               ├── annotation
│   │               │   └── XssProtection.java
│   │               ├── config
│   │               │   └── WebConfig.java
│   │               ├── controller
│   │               │   └── XssController.java
│   │               ├── filter
│   │               │   └── XssFilter.java
│   │               └── util
│   │                   └── XssUtil.java
│   ├── resources
│   │   ├── templates
│   │   │   └── index.html
│   │   ├── application.yml
├── pom.xml
pom.xml 配置
<?xml versinotallow="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.3.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.icoderoad</groupId>
	<artifactId>xss-protection</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>xss-protection</name>
	<description>Demo project for Spring Boot</description>
	
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
		<dependency>
		    <groupId>org.apache.commons</groupId>
		    <artifactId>commons-text</artifactId>
		    <version>1.12.0</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>
application.yml 配置
server:
  port: 8080
spring:
  thymeleaf:
    cache: false
logging:
  level:
    root: INFO
    
xss:
  enabled: true
  type: annotation  # 兩種處理類型 annotation 或者 filter

實(shí)現(xiàn)自定義注解

我們將定義一個自定義注解,用于標(biāo)記需要進(jìn)行 XSS 過濾保護(hù)的控制器方法參數(shù)。

創(chuàng)建注解 @XssProtection
package com.icoderoad.xss_protection.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 用于標(biāo)記需要 XSS 保護(hù)的方法參數(shù)
@Documented
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface XssProtection {
}

自定義注解處理

為了確保我們的注解生效,我們需要在控制器方法參數(shù)上正確處理 @XssProtection 注解。一個有效的方法是通過自定義參數(shù)解析器。

自定義參數(shù)解析器 XssRequestParameterResolver
package com.icoderoad.xss_protection.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import com.icoderoad.xss_protection.annotation.XssProtection;
import com.icoderoad.xss_protection.util.XssUtil;

@Component
public class XssRequestParameterResolver implements HandlerMethodArgumentResolver {

    private static final Logger logger = LoggerFactory.getLogger(XssRequestParameterResolver.class);

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        boolean hasAnnotation = parameter.hasParameterAnnotation(XssProtection.class);
        logger.debug("supportsParameter: {} has annotation: {}", parameter.getParameterName(), hasAnnotation);
        return hasAnnotation;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    	String paramName = parameter.getParameterName();
        String paramValue = webRequest.getParameter(paramName);
        if (paramValue != null) {
            return XssUtil.sanitize(paramValue);
        }
        return null;
    }
}

創(chuàng)建過濾器

接下來,我們實(shí)現(xiàn)一個過濾器,讀取請求的內(nèi)容,并進(jìn)行 XSS 清理。

創(chuàng)建過濾器 XssFilter
package com.icoderoad.xss_protection.filter;

import java.io.IOException;

import com.icoderoad.xss_protection.util.XssUtil;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;

public class XssFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        XssHttpServletRequestWrapper xssRequestWrapper = new XssHttpServletRequestWrapper(httpServletRequest);
        chain.doFilter(xssRequestWrapper, response);
    }

    @Override
    public void destroy() {}

    private static class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
        public XssHttpServletRequestWrapper(HttpServletRequest request) {
            super(request);
        }

        @Override
        public String getParameter(String name) {
            String parameter = super.getParameter(name);
            return parameter == null ? null : XssUtil.sanitize(parameter);
        }

        @Override
        public String[] getParameterValues(String name) {
            String[] values = super.getParameterValues(name);
            if (values != null) {
                for (int i = 0; i < values.length; i++) {
                    values[i] = XssUtil.sanitize(values[i]);
                }
            }
            return values;
        }
    }
}

配置過濾器

在 SpringBoot 配置類中注冊該過濾器或參數(shù)解析器:

配置類 WebConfig
package com.icoderoad.xss_protection.config;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.icoderoad.xss_protection.filter.XssFilter;

import jakarta.servlet.Filter;

@Configuration
public class WebConfig implements WebMvcConfigurer {

	@Value("${xss.enabled}")
	private boolean xssEnabled;

	@Value("${xss.type}")
	private String xssType;
	
	@Autowired
	private XssRequestParameterResolver xssRequestParameterResolver;


	@Bean
	@ConditionalOnProperty(name = "xss.type", havingValue = "filter")
	public Filter xssFilter() {
		return new XssFilter();
	}
	

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
    	if (xssEnabled && "annotation".equalsIgnoreCase(xssType)) {
    		resolvers.add(xssRequestParameterResolver); // 優(yōu)先級最高
    	}
    }

	@Bean
	@ConditionalOnProperty(name = "xss.type", havingValue = "filter")
	public FilterRegistrationBean<XssFilter> xssFilterRegistrationBean() {
		FilterRegistrationBean<XssFilter> registrationBean = new FilterRegistrationBean<>();
		registrationBean.setFilter(new XssFilter());
		registrationBean.addUrlPatterns("/*");
		return registrationBean;
	}

}

創(chuàng)建控制器

創(chuàng)建一個簡單的控制器來演示我們的 XSS 保護(hù)方案:

控制器類 XssController
package com.icoderoad.xss_protection.controller;


import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import com.icoderoad.xss_protection.annotation.XssProtection;

@Controller
public class XssController {

    @GetMapping("/")
    public String index() {
        return "index";
    }

    @PostMapping("/submit")
    public String submit( @XssProtection String input, Model model) {
        model.addAttribute("input", input);
        return "index";
    }
}

創(chuàng)建前端頁面

創(chuàng)建一個 Thymeleaf 模板頁面,用于展示和提交數(shù)據(jù)。

index.html 頁面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>XSS 防護(hù)示例</title>
    <link  rel="stylesheet"/>
    <style>    
      body {
        padding-top: 20px;
    }
    </style>
</head>
<body>
<div class="container">
    <h2 class="text-center">XSS 防護(hù)示例</h2>
    <form action="/submit" method="post" class="mt-4">
        <div class="form-group">
            <label for="input">請輸入文本:</label>
            <input type="text" class="form-control" id="input" name="input" required>
        </div>
        <button type="submit" class="btn btn-primary">提交</button>
    </form>
    <div class="mt-4">
        <h4>提交的文本:</h4>
        <p th:text="${input}"></p>
    </div>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

代碼詳細(xì)講解

  1. 自定義注解:注解 @XssProtection 用于標(biāo)記我們希望保護(hù)的控制器參數(shù)。此注解沒有實(shí)際功能,但在參數(shù)解析器中將使用它來判斷哪些參數(shù)需要進(jìn)行 XSS 過濾。
  2. 過濾器:XssFilter 過濾器會以 XssHttpServletRequestWrapper 包裝請求對象。這一包裝對象的作用是讀取請求體并進(jìn)行 XSS 清理。我們使用了 Apache Commons Text 提供的方法來轉(zhuǎn)義 HTML 字符,防止惡意腳本注入。
  3. 參數(shù)解析器:XssProtectionResolver 自定義參數(shù)解析器在控制器方法被調(diào)用前處理標(biāo)記有 @XssProtection 注解的參數(shù)。參數(shù)解析器使用 StringEscapeUtils.escapeHtml4 方法對參數(shù)值進(jìn)行 HTML 轉(zhuǎn)義,去除潛在的 XSS 攻擊向量。
  4. 前端頁面:前端頁面使用 Thymeleaf 模板引擎,結(jié)合 Bootstrap 框架來創(chuàng)建一個簡單的展示頁面。用戶提交的文本會被展示在頁面上,且變化后的內(nèi)容會通過 XssProtectionResolver 進(jìn)行 XSS 處理后再顯示。
  5. 配置類:在配置類中注冊自定義過濾器和參數(shù)解析器,確保它們在項(xiàng)目啟動時生效。
1. 正常文本
輸入: Hello World
期望輸出: Hello World
說明: 正常文本應(yīng)保持不變,因?yàn)樗话魏螡撛诘膼阂鈨?nèi)容。
2. 簡單的 HTML 標(biāo)簽
輸入: <b>Hello</b>
期望輸出: <b>Hello</b>
說明: 為了防止 HTML 注入,將標(biāo)簽內(nèi)容轉(zhuǎn)義為實(shí)體,確保其不會被瀏覽器解釋為實(shí)際的 HTML。
3. JavaScript 注入
輸入: <script>alert('XSS');</script>
期望輸出: <script>alert('XSS');</script>
說明: 轉(zhuǎn)義 <script> 標(biāo)簽及其內(nèi)容,防止腳本注入并在瀏覽器中執(zhí)行。
4. URL 注入
輸入: <a >Click me</a>
期望輸出: <a >Click me</a>
說明: 鏈接內(nèi)容應(yīng)當(dāng)被轉(zhuǎn)義,防止惡意鏈接注入并自動執(zhí)行。
5. 惡意屬性
輸入: <img src="x" notallow="alert('XSS')">
期望輸出: <img src="x" notallow="alert('XSS')">
說明: 移除或轉(zhuǎn)義潛在的惡意屬性,如 onerror,以防止利用屬性注入執(zhí)行惡意代碼。

總結(jié)

通過上述配置,我們創(chuàng)建了一個包含完整 XSS 防護(hù)的 Spring Boot 應(yīng)用。自定義注解、過濾器和參數(shù)解析器的結(jié)合使我們的解決方案靈活且易于擴(kuò)展。此方案不僅能有效防止 XSS 攻擊,還能保證應(yīng)用的可維護(hù)性和代碼的整潔度。

責(zé)任編輯:武曉燕 來源: 路條編程
相關(guān)推薦

2010-04-30 15:45:09

2009-09-13 20:28:38

Linq插入數(shù)據(jù)

2016-03-17 17:35:15

云容器虛擬化管理Docker

2020-05-11 10:59:02

PythonWord工具

2015-01-04 15:36:52

XSS漏洞XSS

2025-03-11 08:34:22

2013-08-07 10:00:03

XSS谷歌

2022-09-16 08:04:25

阿里云權(quán)限網(wǎng)絡(luò)

2021-09-03 08:23:21

Vue 插槽子組件

2009-12-11 15:37:58

Linux日志處理

2017-05-11 15:01:43

Androidweb布局

2024-05-06 08:56:31

PythonHTML正則表達(dá)式

2023-12-31 09:06:08

2024-07-17 08:29:20

2024-08-29 08:58:30

JPA編寫數(shù)據(jù)操

2009-04-27 11:17:51

網(wǎng)絡(luò)管理子網(wǎng)劃分

2020-12-07 16:20:53

Python 開發(fā)編程語言

2020-08-23 12:27:39

測試接口技巧

2009-10-23 17:51:51

Oracle用戶密碼

2025-02-07 08:39:32

Shell部署測試
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號