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/n/180278.html