Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC - How to check that no unexpected query string parameters has been passed?

I have a web service written in Spring MVC. It can be used by 3rd party developers. Our methods have a lot of optional parameters (passed in the query string).

I want to make sure that all the query string parameters are spelled correctly and there is no typos. Is there an easy way to do it? Method signature example:

 @RequestMapping(value = {"/filter"}, method = RequestMethod.GET)
    @ResponseBody
    public List<MetricType> getMetricTypes(    
            @RequestParam(value = "subject", required = false) Long subjectId,
            @RequestParam(value = "area", required = false) Long areaId,
            @RequestParam(value = "onlyImmediateChildren", required = false) Boolean onlyImmediateChildren,   
            @RequestParam(value = "componentGroup", required = false) Long componentGroupId    
            ) throws Exception
    {
        //Some code
    }

If somebody calls this method with "onlyImediateChildren=true" parameter (a typo) instead of "onlyImmediateChildren=true", Spring MVC will ignore the typoed parameter and will assume "onlyImmediateChildren" is null. Developer will get slightly incorrect list of results and will not notice the error. Such issues could be widespread and difficult to diagnose. I want to check there is no typoed params in query string to prevent such issues.

UPDATE

It is possible to extract the list of actual parameters from the query string. Then it could be compared with the list of the allowed parameters. If I hardcode the allowed parameter list, it will duplicate the method signature. I wonder if it is easy to extract a list of allowed parameters from the method signature (e.g. by @RequestParam annotation)?

Many thanks

Maxim

like image 210
Maxim Eliseev Avatar asked Apr 04 '12 11:04

Maxim Eliseev


2 Answers

You could implement your own HandlerInterceptor. In preHandle method you can obtain all HandlerMethod's parameters annotated with @RequestParameter. These will be all allowed parameters in request.

like image 91
sinuhepop Avatar answered Oct 05 '22 04:10

sinuhepop


Here is my implementation of an HandlerInterceptor which will only accept the parameters which are explicitely defined by a parameter annotation:

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Component
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.method.HandlerMethod
import org.springframework.web.servlet.HandlerInterceptor

/**
 * Interceptor which assures that only expected [RequestParam]s are send.
 */
@Component
class UnexpectedParameterHandler : HandlerInterceptor {

    override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {
        if (handler is HandlerMethod) {
            val queryParams = request.parameterNames.toList()
            val expectedParams = handler.methodParameters
                .map { methodParameter ->
                    val requestParamName = methodParameter.getParameterAnnotation(RequestParam::class.java)?.name
                    val parameterName = methodParameter.parameter.name
                    requestParamName ?: parameterName
                }

            val unknownParameters = queryParams.minus(expectedParams)
            if (unknownParameters.isNotEmpty()) {
                response.writer.write("unexpected parameter $unknownParameters")
                response.status = HttpStatus.BAD_REQUEST.value()
                return false
            }
        }

        return super.preHandle(request, response, handler)
    }
}
like image 36
Tobias Avatar answered Oct 05 '22 03:10

Tobias