我目前有这个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();
}
这可能吗?
答案 0 :(得分:8)
执行此操作的最佳方式IMO是使用自定义注释创建自定义HandlerMethodArgumentResolver
,使用自定义注释@Segment
:
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();
}
}
答案 1 :(得分:1)
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"
}
如果标题丢失。
3)使用过滤器
如果要在多种方法中使用它,可以使用某些过滤器自动执行检查。在您的自定义过滤器中,只需获取标题(如方法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。
答案 2 :(得分:1)
有一个功能请求Spring积压,结帐JIRA。但是,我能够在Controller上使用PostgreSQL
注释来实现您的尝试。
@Validated
此处@RestController
@RequestMapping("/user")
@Validated
public class UserController {
@GetMapping("/{loginId}")
public User getUserBy(@PathVariable @LoginID final String loginId) {
// return some user
}
}
是自定义验证程序。而@LoginID
来自@Validated
,可以解决问题。
答案 3 :(得分:0)
只需添加以下类。 在“ 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);
}
}