简体   繁体   English

Spring 启动请求 Header 验证

[英]Spring Boot Request Header Validation

I am using Spring Boot 2.3.8 for creating rest services.我正在使用 Spring Boot 2.3.8 创建 rest 服务。 I have a requirement to validate the request headers such that it should have certain headers otherwise throw error.我需要验证请求标头,以便它应该具有某些标头,否则会引发错误。 This should be common for all the methods or services.这对于所有方法或服务应该是通用的。 I tried below,我在下面尝试过,

public ResponseEntity<Object> addEmployee(
        @RequestHeader(name = "header1", required = true) String header1,
        @RequestHeader(name = "header2", required = true) String header2,
        @RequestBody Employee employee) 
                 throws Exception 
    { 

But I need to add this for all the methods in all the controllers.但是我需要为所有控制器中的所有方法添加它。 If this is the case how can I throw an error like "Header1 missing in request headers" / "header2 missing in request headers" for all the services globally?如果是这种情况,我如何为全球所有服务抛出诸如“请求标头中缺少 Header1”/“请求标头中缺少标头 2”之类的错误?

If you have Zuul in place then you can read the request header attributes there in pre route and on validation failure reply back to the request with error populated.如果您有 Zuul,那么您可以在预路由中读取请求 header 属性,并在验证失败时回复填充错误的请求。

This is a cross-cutting concern and should be done using AOP .这是一个横切关注点,应该使用AOP来完成。 Since you're using Spring , you can do the following:由于您使用的是Spring ,您可以执行以下操作:

  1. Create an annotation called ValidateHeaders :创建一个名为ValidateHeaders的注释:

    public @interface ValidateHeaders {}

  2. Create a @Before advice that intercepts methods annotated with @ValidateHeaders :创建一个@Before通知,拦截使用@ValidateHeaders注释的方法:

     @Before("@annotation(com.somepackage.ValidateHeaders)") public void controllerProxy(JoinPoint jp) { Object[] args = jp.getArgs(); //validation logic, throw exception if validation fails }

Note that you'll have to extract the fields using reflection as:请注意,您必须使用反射提取字段:

Annotation[][] pa = ms.getMethod().getParameterAnnotations();

You can iterate through all the annotations and search for request headers as:您可以遍历所有注释并搜索请求标头:

if(annotations[i][j].annotationType().getName().contains("RequestHeader")) {
    RequestHeader requestHeader = (RequestHeader) m.getParameterAnnotations()[i][j];
    //now access fields in requestHeader to do the validation
}

Here's an article that can get you started with Advice types: https://www.baeldung.com/spring-aop-advice-tutorial这是一篇可以让您开始使用建议类型的文章: https://www.baeldung.com/spring-aop-advice-tutorial

For global use you can register an interceptor.对于全局使用,您可以注册一个拦截器。

@Component
public class MyHandlerInterceptor implements HandlerInterceptor {
    
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception arg3) throws Exception {
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView model) throws Exception {
    }

   @Override
   public boolean preHandle(HttpServletRequest request,
   HttpServletResponse response, Object handler) throws Exception {

    
    //here check headers contained in request object
    if (request.getHeader("header1") == null || request.getHeader("header2") == null) {
      response.getWriter().write("something");
      response.setStatus(someErrorCode);

      return false;
   }

   return true;
} 

And then register it然后注册

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

@Autowired
private MyHandlerInterceptor interceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(interceptor).addPathPatterns("/**");
 }
}

This is what filters are for.这就是过滤器的用途。 You want to filter out requests based on a header being there or not and return an error if its missing.您想根据 header 是否存在过滤掉请求,如果丢失则返回错误。 Extend OncePerRequestFilter optionally override shouldNotFilter if you do not want it to be used for all request OR you could implement a normal Filter and use FilterRegistrationBean to register it only for a specific path.如果您不希望将它用于所有请求,则扩展OncePerRequestFilter可选择覆盖shouldNotFilter或者您可以实现普通Filter并使用FilterRegistrationBean仅为特定路径注册它。

then in the filter you could throw an exception and let Spring figure out how to display that, or actually set the response to something meaningful.然后在过滤器中你可以抛出一个异常并让 Spring 弄清楚如何显示它,或者实际上将响应设置为有意义的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM