私は現在このRequestMapping
を持っていますが、正規表現による検証を使用しています:
@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) @Valid @Pattern(regexp = SEGMENTS_REGEX) String apiKeyHeader) {
// Stuff here...
}
ただし、正規表現では不十分です。代わりに、ヘッダー属性に対してカスタム検証を実行したいと考えています。
if (!API_KEY_LIST.contains(apiKeyHeader)) {
throw Exception();
}
これは可能ですか?
このIMOを行う最良の方法は、カスタムアノテーション@Segment
を使用して、次のようなカスタムHandlerMethodArgumentResolver
を作成することです。
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;
}
}
}
次に、コントローラの署名は次のようになります。
@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...
}
ハンドラーメソッドの引数リゾルバーをWebMvcConfigurationAdapterに登録します。
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(segmentHandler());
}
@Bean
public SegmentHandlerMethodArgumentResolver segmentHandler() {
return new SegmentHandlerMethodArgumentResolver();
}
}
すでに機能リクエストの春のバックログ、チェックアウト [〜#〜] jira [〜#〜] があります。しかし、私はあなたが@Validated
コントローラーの注釈。
@RestController
@RequestMapping("/user")
@Validated
public class UserController {
@GetMapping("/{loginId}")
public User getUserBy(@PathVariable @LoginID final String loginId) {
// return some user
}
}
ここに @LoginID
はカスタムバリデーターです。そして@Validated
から org.springframework.validation.annotation.Validated
トリックを行います。
1)手動で確認
HttpServletRequestを挿入して、ヘッダーを確認できます。
@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)ヘッダーを挿入します
@RequestMapping(value = "/test", method = RequestMethod.POST)
public ResponseEntity<String> test(@RequestHeader(value="myheader") String myheader){
return new ResponseEntity<String>(HttpStatus.OK);
}
それは戻ります:
{
"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"
}
ヘッダーがない場合。
)フィルターを使用
複数のメソッドで使用する場合は、フィルターを使用してチェックを自動化できます。カスタムフィルターで(メソッド1のように)ヘッダーを取得し、ヘッダーが欠落している場合は、400または必要なもので応答します。私にとっては、コントローラーメソッドでヘッダー値を使用せず、存在することを検証するだけでよい場合に意味があります。
@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();
}
リクエストをスキップ
@RequestMappingでheaders属性を使用する場合
@RequestMapping(value = "/test", method = RequestMethod.POST,
headers = {"content-type=application/json"})
リクエストを受け取るハンドラが他にない場合、これは404になります。
次のクラスを追加するだけです。 「doFilter」メソッド内で検証を行い、適切な応答コードを設定します。
@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);
}
}