用自定义注解替代@RequestBody实现xss过滤的尝试

需求背景

post请求中的body参数,会解析成 @RequestBody 注解的对象。现在需要把该对象的所有string属性进行XSS过滤,XSS过滤是已有的轮子。

设计思路
  1. 面向扩展开放,面向修改关闭原则。新定义一个注解解决这类问题:@XssCleaned
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface XssCleaned {
}
复制代码
实现
  1. 自定义扩展HandlerMethodArgumentResolver,由于需要替代@RequestBody,解析MediaType=application/*+json的请求中的body参数 (参见MappingJackson2HttpMessageConverter) 所以使用的自定义扩展HandlerMethodArgumentResolver的子类RequestResponseBodyMethodProcessor
public class XssCleanedResolver extends RequestResponseBodyMethodProcessor{

    public XssCleanedResolver(List<HttpMessageConverter<?>> converters) {
        super(converters);
   }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(XssCleaned.class);
   }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        Object o = super.resolveArgument(parameter,mavContainer,webRequest,binderFactory);
        //将所有string类型的feild进行xss过滤
        PostBodyUtil.cleanXSSfields(o);
        return o;
   }

}
复制代码
  1. 遍历string属性,进行过滤
public class PostBodyUtil {

    /**
     * 所有string类型的字段都进行xss过滤
     * @return
     */
    public static boolean cleanXSSfields(Object o){
        Arrays.stream(BeanUtils.getPropertyDescriptors(o.getClass())).forEach(t->{
                    if (t.getPropertyType().equals(String.class)){
                        String fieldValue = "";
                        try {
                            fieldValue = (String) t.getReadMethod().invoke(o);
                            t.getWriteMethod().invoke(o,
                                    AntiXssUtil.decodeHtml(AntiXssUtil.cleanHtml(fieldValue)));
                       } catch (IllegalAccessException  | InvocationTargetException e) {
                            LoggerHandler.error(e, "cleanHtml failed!"+t.getName()+":"+fieldValue);
                            return;
                       }
                   }
               }
       );
        return true;
   }
}
复制代码
  1. 注册该resolver 在自定义扩展的WebMvcConfigurationSupport中,重写addArgumentResolvers,将该resolver注册。
@Override
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    argumentResolvers.add(new XssCleanedResolver(converters));
}
复制代码
  1. 使用注解实例
@PostMapping("/updateShipments")
public PlatformReturn updateShipments(@XssCleaned Shipment shipment, @CurrentUser SysUser user){

    return myOrderService.updateShipments(shipment,user);
}
复制代码

这样,shipment对象的每个string属性都是经过xss过滤的,其它功能与 @RequestBody 功能相同。

over

转载于:https://juejin.im/post/5c80c3d7f265da2da771f752

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Cloud Gateway中,可以使用BodyInserter类方法来实现XSS过滤。 首先,你需要创建一个实现BodyInserter接口的自定义类,用于对请求和响应的body进行修改。例如: ```java public class XssBodyInserter implements BodyInserter<Object, ReactiveHttpOutputMessage> { private final BodyInserter<Object, ReactiveHttpOutputMessage> delegate; public XssBodyInserter(BodyInserter<Object, ReactiveHttpOutputMessage> delegate) { this.delegate = delegate; } @Override public Mono<Void> insert( Publisher<? extends Object> input, ReactiveHttpOutputMessage outputMessage) { // 对请求或响应的body进行XSS过滤 return delegate.insert(input, outputMessage); } @Override public List<HttpMessageWriter<?>> messageWriters() { return delegate.messageWriters(); } } ``` 然后,在路由定义中使用该自定义类来对请求和响应的body进行修改。例如: ```java @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route(r -> r.path("/api/**") .filters(f -> f.modifyRequestBody(String.class, Object.class, MediaType.APPLICATION_JSON_VALUE, (exchange, s) -> { // 对请求的body进行XSS过滤 return Mono.just(XssUtils.xssEncode(s)); }) .modifyResponseBody(Object.class, String.class, MediaType.APPLICATION_JSON_VALUE, (exchange, s) -> { // 对响应的body进行XSS过滤 return Mono.just(XssUtils.xssEncode(s)); })) .uri("lb://backend-service")) .build(); } ``` 在上面的示例中,我们使用了`modifyRequestBody`和`modifyResponseBody`方法来分别对请求和响应的body进行修改,并调用自定义的`XssUtils.xssEncode`方法来进行XSS过滤。 需要注意的是,该方法只能对JSON格式的请求和响应进行XSS过滤,如果请求和响应是其他格式的,需要进行相应的修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值