XSS(Cross-site scripting)跨站腳本攻擊是一種常見的Web攻擊,攻擊者往Web頁面里插入惡意的腳本代碼,使得用戶在瀏覽頁面或提交表單的時候,執行惡意腳本,從而達到攻擊目的。為了防止XSS攻擊,Springboot提供了多種方式去過濾用戶輸入的數據,保證系統的安全穩定。
一、 Springboot過濾器
1、過濾器介紹
過濾器是用於攔截請求與響應,可以用於URL、Servlet、JSP、靜態文件等資源的攔截。Springboot的過濾器實現了javax.servlet.Filter接口,提供了過濾器的常見功能,是一種非常常用的過濾方式。
2、過濾器示例
在Springboot中,過濾器是通過@Bean把過濾器加入到過濾器鏈中的,可以通過註解@WebFilter實現。以下示例會構建一個過濾器,對所有請求進行XSS過濾:
@WebFilter(urlPatterns = "/*", filterName = "xssFilter") 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 { chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response); } @Override public void destroy() { } }
在過濾器中,我們通過構建XssHttpServletRequestWrapper來過濾請求。這個Wrapper里重寫了getParameter方法,對請求中的參數進行了過濾。XssHttpServletRequestWrapper的實現如下:
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { public XssHttpServletRequestWrapper(HttpServletRequest request) { super(request); } @Override public String getParameter(String name) { String value = super.getParameter(name); if (value == null) { return null; } return HtmlUtils.htmlEscape(value); } }
在getParameter方法中,我們使用了org.springframework.web.util.HtmlUtils的htmlEscape方法對請求參數進行了過濾,把所有的HTML標籤都轉換成了實體,防止了XSS攻擊。
二、 Springboot註解
1、註解介紹
Springboot通過註解的方式來處理XSS過濾,可以直接在Controller層的方法參數上使用@Validated註解,在參數中使用@NotBlank或其他JSR303註解,並配合@RequestBody、@RequestParam可以過濾掉所有HTML標籤,非常方便易用。
2、註解示例
以下例子演示了如何使用@RequestBody和@RequestParam結合JSR303註解來實現對控制器請求參數的過濾:
@RestController public class UserController { @PostMapping("/user") public void addUser(@Validated @RequestBody UserDTO userDTO) { // Todo } @GetMapping("/users") public List getUsers(@RequestParam @NotBlank String name) { // Todo } }
在addUser方法中,我們使用了@Validated註解,同時在UserDTO的name字段上使用了@NotBlank註解,來實現對請求參數的過濾。在getUsers方法中,我們也顯示的用@RequestParam聲明了參數name,並使用了@NotBlank註解來過濾請求。
三、Springboot過濾器加上自定義註解
1、自定義註解介紹
自定義註解可以讓我們更好的管理XSS過濾,使得代碼更加可讀、易用、易維護,可以在Springboot過濾器的基礎上添加自定義註解,來實現更加靈活的過濾。
2、自定義註解示例
以下代碼演示了如何在過濾器中添加自定義註解:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface XssSecurity { String[] excludes() default {}; } @Aspect @Component public class XssSecurityAspect { private static final Logger logger = LoggerFactory.getLogger(XssSecurityAspect.class); @Pointcut("@annotation(cn.example.demo.annotation.XssSecurity)") public void xssPointCut() { } @Before("xssPointCut() && @annotation(xssSecurity)") public void doBefore(JoinPoint joinPoint, XssSecurity xssSecurity) throws Throwable { ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (servletRequestAttributes == null) { return; } HttpServletRequest request = servletRequestAttributes.getRequest(); if (checkUrlExclude(request.getRequestURI(), xssSecurity.excludes())) { return; } XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(request); request.setAttribute("body", xssRequest.getBody()); for (Object arg : joinPoint.getArgs()) { if (arg instanceof XssHttpServletRequestWrapper || arg instanceof MultipartFile) { continue; } Object o = xssSecurity(xssRequest, arg); Method method = reflectMethod(joinPoint, arg); if (null != method) { method.invoke(joinPoint.getTarget(), o); } } } public Object xssSecurity(HttpServletRequest request, Object param) { if (param == null) { return null; } if (param instanceof String) { return HtmlUtils.htmlEscape((String) param); } else if (param instanceof Map) { Map
在這個示例中,我們使用了AOP的方式來處理XSS過濾,通過自定義註解@XssSecurity來實現。在XssSecurityAspect的實現中,我們通過@Pointcut(“@annotation(cn.example.demo.annotation.XssSecurity)”)註解來定義Pointcut。在doBefore方法中,主要是通過反射的方式,對請求進行過濾。我們通過checkUrlExclude方法來判斷當前請求是否在排除列表中,如果在就不進行過濾。
四、Spring-boot-starter-validation
1、Spring-boot-starter-validation介紹
Spring-boot-starter-validation是Springboot提供的JSR303驗證依賴庫,可以非常方便的對請求數據進行校驗,包括數據類型、參數是否為空、參數是否在指定的範圍內等等。使用起來非常方便簡單。
2、Spring-boot-starter-validation示例
以下代碼演示了如何使用Spring-boot-starter-validation的@NotBlank註解進行參數的非空判斷:
@Data @NoArgsConstructor @AllArgsConstructor public class UserDTO { @NotBlank(message = "用戶名不能為空") private String name; } @RestController public class UserController { @PostMapping("/user") public void addUser(@Validated @RequestBody UserDTO userDTO) { // Todo } }
在這個示例中,我們使用了@NotBlank(message = “用戶名不能為空”)註解對UserDTO中的name字段進行了非空判斷。如果請求中的name為空,Springboot會返回錯誤信息”用戶名不能為空”,並返回400響應碼。
五、Spring Security過濾器鏈
1、Spring Security介紹
Spring Security是Spring官方的安全框架,提供了一系列的安全服務,包括權限認證、資源保護等,Spring Security內置了很多過濾器,可以通過配置來加入過濾器鏈進行XSS過濾。
2、Spring Security示例
以下代碼演示了如何在Spring Security配置中添加XSS過濾器來保護應用:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean public FilterRegistrationBean xssFilterRegistrationBean() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new XssFilter()); registrationBean.addUrlPatterns("/*"); registrationBean.setName("xssFilter"); return registrationBean; } }
我們在SecurityConfig中通過@Bean註解,加入了一個名為xssFilter的過濾器,把這個過濾器添加到了Spring Security的過濾器鏈中。這個過濾器實現方式與第一部分中的過濾器是一樣的,都是通過XssHttpServletRequestWrapper來過濾請求。
六、小結
通過以上介紹,我們可以看出Springboot提供了多種方式進行XSS過濾,包括過濾器、註解、自定義註解和結合Spring Security等。不同的過濾方式有各自的優缺點和使用場景,開發人員可以結合具體需求來選擇最合適的方式進行過濾。XSS攻擊是一種非常常見且危險的攻擊方式,合理的XSS過濾能夠保障系統的安全穩定。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/180278.html