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-hk/n/180278.html
微信掃一掃
支付寶掃一掃