web-dev-qa-db-de.com

Benutzerdefinierte Validierung bei RequestHeader Spring Boot

Ich habe derzeit diesen Request-Mapper, bei dem ich mit einem REGEX eine Validierung eines Request-Parameters durchführe.

@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 kann ich mit einem Muster validieren:

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

Ich möchte jedoch einige benutzerdefinierte Überprüfungen für das Header-Attribut durchführen, d. H.

if (!API_KEY_LIST.contains(apiKeyHeader)) {
    throw Exception();
}
7
ptimson

Am besten erstellen Sie dieses IMO, indem Sie eine benutzerdefinierte HandlerMethodArgumentResolver erstellen, die mit einer benutzerdefinierten Anmerkung @Segment so aussehen würde:

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 sieht Ihre Controller-Signatur so 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 registrieren den Handler-Methodenauflöser in Ihrem WebMvcConfigurationAdapter:

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {

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

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

}
7
Ulises

Es gibt bereits eine Funktionsanforderung Spring Backlog, Kasse JIRA . Mit @Validated Annotation auf dem Controller konnte ich jedoch erreichen, was Sie versuchen.

@RestController
@RequestMapping("/user")
@Validated
public class UserController {

   @GetMapping("/{loginId}")
   public User getUserBy(@PathVariable @LoginID final String loginId) {
      // return some user
   }
}

Hier ist @LoginID der benutzerdefinierte Prüfer. Und @Validated ist von org.springframework.validation.annotation.Validated, der den Trick macht.

1
Sarvesh Dubey

1) Manuell prüfen

Sie können die HttpServletRequest-Funktion einfügen und die Header überprüfen.

@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 Header

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

Das wird wiederkommen:

{
  "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) Filter verwenden

Sie können die Prüfung mit einem Filter automatisieren, wenn Sie sie für mehrere 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 möchten. Für mich ist das sinnvoll, wenn Sie den Header-Wert nicht in der Controller-Methode verwenden und nur prüfen müssen, ob 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();
}

Anfrage überspringen

Wenn Sie das Header-Attribut in @RequestMapping verwenden

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

dies führt zu 404, wenn kein anderer Handler die Anforderung entgegennimmt.

1
Evgeni Dimitrov

Fügen Sie einfach die folgende Klasse hinzu.

@Configuration
public class ApiHeaderFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        String token = request.getHeader("token");
        if (StringUtil.isNullOrEmpty(token)) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }
        filterChain.doFilter(servletRequest,servletResponse);
    }
}
0
Pruthviraj