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;
}
主要是两个方法:supportsParameter
、resolveArgument
当supportsParameter
方法的返回值为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了 😃