2

I have a Spring 3.2 application and I've created a REST API that uses a token-based security. Every REST JSON payload contains a "token" field that is used to perform security validation.

The controller methods are like this:

@RequestMapping(value = "/something", method = RequestMethod.POST)
public
@ResponseBody
Map something(@RequestBody SomethingParams params) {
}

where SomethingParams has a token field, and is automatically filled in by Spring from the JSON body of the request.

Is there a way to automatically have a validator invoked on all the controller methods to check that parameters such as SomethingParams have a valid token?

Previously I used an Interceptor, and the token was included in the query string, but now, since it's in the body of the request, I would have to parse the JSON in the interceptor in order to check it. Since Spring already parses the JSON to bind the parameters, I'm curious if there's a smarter way. Ideally just with some global or controller-level settings (not per method).

1

3 Answers 3

3

You can use a spring Validator for such cases.

@Component
public class SomethingParamsValidator implements Validator {
  @Override
  public boolean supports(Class<?> clazz) {
    return clazz.isAssignableFrom(SomethingParams.class);
  }

  @Override
  public void validate(Object o, Errors errors) {
    SomethingParams sp = (SomethingParams)o;
    validateToken(sp.getToken(), errors);
  }

  private void validateToken(String token, Errors errors) {
    if (!TokenUtils.isValid(token)) {
      errors.rejectValue("token", "foo", "Token is invalid");
    }
  }
}

Then you register it in your Controller by adding the following method

@Autowired
SomethingParamsValidator somethingParamsValidator;

@InitBinder
protected void initBinder(WebDataBinder binder) {
    binder.setValidator(somethingParamsValidator);
}

Finally all you have to add is the @Valid annotation on your SomethingParams object and it will be validated.

@RequestMapping(value = "/something", method = RequestMethod.POST)
public @ResponseBody Map something(@Valid @RequestBody SomethingParams params) {
    // ...
}
Sign up to request clarification or add additional context in comments.

1 Comment

Is there a way to avoid using the @Valid annotation on every method? Such as specifying it on the parameters class?
0

You can make base class with token field annotated with JSR-303 @NotNull and extend from it.

public class ParamsBase {
  @NotNull
  private String token;
  // getters, setters ...
}
public class SomethingParams extends ParamsBase {...}

And then just mark parameter with @Valid:

@RequestMapping(value = "/something", method = RequestMethod.POST)
public @ResponseBody Map something(@Valid @RequestBody SomethingParams params) {
    // ...
}

Spring will automatically validate parameter with JSR-303 implementation available at runtime.

I usually use hibernate-validator as implementation provider:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.0.1.Final</version>
</dependency>

Comments

0

You can also implement your own Aspect, which will intercept all controller methods and validate params. This will give you opportunity to get rid of @Valid annotation. But unfortunately I don't have time for full example.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.