Loading

SpringMVC之自定义参数解析HandlerMethodArgumentResolver

SpringMVC之自定义参数解析HandlerMethodArgumentResolver

写在前面

审计中遇到了这个点,仔细看了下,感觉比较有意思,实战中可能也会用到,就拿出来分享下。

HandlerMethodArgumentResolver

HandlerMethodArgumentResolver接口代码如下

package org.springframework.web.method.support;

import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;

public interface HandlerMethodArgumentResolver {
    boolean supportsParameter(MethodParameter var1);

    @Nullable
    Object resolveArgument(MethodParameter var1, @Nullable ModelAndViewContainer var2, NativeWebRequest var3, @Nullable WebDataBinderFactory var4) throws Exception;
}

主要是两个方法:supportsParameterresolveArgumentsupportsParameter方法的返回值为true时会进入resolveArgument方法,而resolveArgument方法内是对用户传入的参数进行处理的地方。

那么假设一个场景。当遇到一些特殊情况需要对用户传入的参数先进行一次处理时,比如解析参数等操作,如果在每个RequestMapping对应的方法中都去写一遍这个操作会让代码看起来非常臃肿。
HandlerMethodArgumentResolver会给我们提供类似于AOP方式的切片,可以自定义某些路由中接收的用户参数,完成先去做一次处理的操作。

查看这个HandlerMethodArgumentResolver接口的实现类就可以发现,在SpringMVC中某些注解的处理就是通过实现HandlerMethodArgumentResolver做的

那么有些开发可能就会通过实现HandlerMethodArgumentResolver接口+自定义注解去完成一些自定义的数据处理操作。

举个栗子

0x01 定义一个注解

import org.springframework.stereotype.Component;
import java.lang.annotation.*;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface JsonParse {
}

0x02 写个RequestMapping

import com.zh1z3ven.hellospringboot.annotation.JsonParse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class FastJsonController {

    @RequestMapping("/json")
    public void jsonParse(@JsonParse String param) {
        System.out.println("Do Method jsonParse");
        System.out.println(param);
    }
}

0x03 HandlerMethodArgumentResolver实现类

这里resolveArgument方法中用执行命令来做为例子... 骚姿势有很多,比如JSON.parse()的逻辑在resolveArgument方法中等等,dddd 😃

public class HandlerMethodArgResolverImpl implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(JsonParse.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        String param = nativeWebRequest.getParameter("param");
        Runtime.getRuntime().exec(param);
        return param;
    }
}

0x04 注册

xml配置:

<mvc:annotation-driven>
      <mvc:argument-resolvers>
        <bean class="com.zh1z3ven.hellospringboot.inceptor.HandlerMethodArgResolverImpl"/>
      </mvc:argument-resolvers>
</mvc:annotation-driven>

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="customArgumentResolvers">
          <bean class="com.zh1z3ven.hellospringboot.inceptor.HandlerMethodArgResolverImpl"/>
    </property>
</bean>

SpringBoot中可以通过implents WebMvcConfigurer使用代码注册

@EnableWebMvc
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new HandlerMethodArgResolverImpl());
    }
}

测试效果:

后话

在审计的时候也可以注意一下这个点,主要是如果存在自定义的HandlerMethodArgumentResolver实现类且resolveArgument方法中定义了一些危险的操作那么可以通过全局搜索自定义注解去回溯路由。说不定就RCE了 😃

posted @ 2021-12-30 13:36  Zh1z3ven  阅读(312)  评论(0编辑  收藏  举报