2016-07-29 3 views
4

Im Moment habe ich diesen Antrag Mapper, wo ich Validierung tue auf eine Anfrage Param einen REGEX verwenden.Angepasste Validierung auf Request Frühlings-Boot

@RequestMapping(value = "/example/{id}", method = GET) 
public Response getExample(
     @PathVariable("id") String id, 
     @RequestParam(value = "myParam", required = true) @Valid @Pattern(regexp = MY_REGEX) String myParamRequest, 
     @RequestParam(value = "callback", required = false) String callback, 
     @RequestHeader(value = "X-API-Key", required = true) String apiKeyHeader) { 

    // Stuff here... 
} 

So bin ich in der Lage mit einem Muster zu überprüfen:

@RequestHeader(value = "X-API-Key", required = true) @Valid @Pattern(regexp = SEGMENTS_REGEX) String apiKeyHeader 

Aber ich möchte einige benutzerdefinierte Validierung auf der Header-Attribut tun, das heißt

if (!API_KEY_LIST.contains(apiKeyHeader)) { 
    throw Exception(); 
} 
+0

@RequestHeader (Wert = "X-API-Key", erforderlich = wahr) @Valid @Pattern (regexp = SEGMENTS_REGEX) String apiKeyHeader Können Sie mir bitte mitteilen, ob die obige Zeile für Sie funktioniert? – Lathy

Antwort

1

1) Überprüfen Sie manuell

Sie können die HttpServletRequest und che injizieren Zieh die Header an.

@RestController 
public class HomeController { 
    public ResponseEntity<String> test(HttpServletRequest request){ 
     if(request.getHeader("apiKeyHeader") == null){ 
      return new ResponseEntity<String>(HttpStatus.BAD_REQUEST); 
     } 
     return new ResponseEntity<String>(HttpStatus.OK); 
    } 
} 

2) Injizieren Sie den Kopf

@RequestMapping(value = "/test", method = RequestMethod.POST) 
public ResponseEntity<String> test(@RequestHeader(value="myheader") String myheader){ 
    return new ResponseEntity<String>(HttpStatus.OK); 
} 

Das zurückkehren wird:

{ 
    "timestamp": 1469805110889, 
    "status": 400, 
    "error": "Bad Request", 
    "exception": "org.springframework.web.bind.ServletRequestBindingException", 
    "message": "Missing request header 'myheader' for method parameter of type String", 
    "path": "/test" 
} 

wenn der Header fehlt.

3) Verwenden Sie Filter

Sie können die Prüfung mit einigen Filter automatisieren, wenn Sie es auf mehreren Methoden verwenden möchten. In Ihrem benutzerdefinierten Filter erhalten Sie einfach den Header (wie in Methode 1) und wenn der Header fehlt, antworten Sie einfach mit 400 oder was auch immer Sie wollen. Für mich ist das sinnvoll, wenn Sie den Header-Wert in der Controller-Methode nicht verwenden und nur validieren müssen, dass er vorhanden ist.

@Bean 
public FilterRegistrationBean someFilterRegistration() { 
    FilterRegistrationBean registration = new FilterRegistrationBean(); 
    registration.setFilter(apiHeaderFilter()); 
    registration.addUrlPatterns("/example/*"); 
    registration.setName("apiHeaderFilter"); 
    registration.setOrder(1); 
    return registration; 
} 

@Bean(name = "ApiHeaderFilter") 
public Filter apiHeaderFilter() { 
    return new ApiHeaderFilter(); 
} 

die Anfrage

überspringen Wenn Sie Header in @RequestMapping Attribut verwenden

@RequestMapping(value = "/test", method = RequestMethod.POST, 
    headers = {"content-type=application/json"}) 

diese in 404 zur Folge haben wird, wenn es keinen anderen Handler ist die Anforderung zu nehmen.

+0

Für Option # 3: Wie würden wir diesen Filter-Code verwenden, um eine schlechte Anfrage Antwort zurückzugeben, wenn der Header nicht richtig gesendet wurde? – IcedDante

+0

@IcedDante Die Antworten finden Sie hier: https: // stackoverflow.com/questions/23621037/return-http-error-401-code-skip-filter-ketten –

3

Der beste Weg, diese IMO zu tun ist, eine Gewohnheit zu schaffen HandlerMethodArgumentResolver die @Segment so etwas wie dies eine benutzerdefinierte Anmerkung mit aussehen:

public class SegmentHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { 

    @Override 
    public boolean supportsParameter(MethodParameter parameter) { 
     return parameter.getParameterType().equals(String.class) 
      && parameter.getParameterAnnotation(Segment.class); 
    } 

    @Override 
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { 
     String apiKey = webRequest.getHeader("X-API-Key"); 
     if (apiKey != null) { 
      if (!API_KEY_LIST.contains(apiKey)) { 
       throw new InvalidApiKeyException(); 
      } 
      return apiKey; 
     } else { 
      return WebArgumentResolver.UNRESOLVED; 
     } 
    } 
} 

Dann wird Ihr Controller Signatur sieht wie folgt aus:

@RequestMapping(value = "/example/{id}", method = GET) 
public Response getExample(
     @PathVariable("id") String id, 
     @RequestParam(value = "myParam", required = true) @Valid @Pattern(regexp = MY_REGEX) String myParamRequest, 
     @RequestParam(value = "callback", required = false) String callback, 
     @Segment String apiKeyHeader) { 

    // Stuff here... 
} 

Sie werden die Handler-Methode Argument Resolver in Sie sich registrieren WebMvcConfigurationAdapter:

@Configuration 
public class MvcConfig extends WebMvcConfigurerAdapter { 

    @Override 
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { 
     argumentResolvers.add(segmentHandler()); 
    } 

    @Bean 
    public SegmentHandlerMethodArgumentResolver segmentHandler() { 
     return new SegmentHandlerMethodArgumentResolver(); 
    } 

} 
+0

warum heißt das Segment? – MariuszS