修改请求头进入控制器和响应头,留下Spring Boot RestController

时间:2018-03-19 18:18:02

标签: spring-boot servlets spring-restcontroller

这感觉它应该是一件简单的事情,但我仍然是SpringBoot和整个Servlet生态系统的新手,所以它不是很明显。我想要一个类似于HandlerInterceptor的接口,它允许我在控制器中完成后修改请求和响应对象。更好的是装饰映射注释,因此我可以指定哪些控制器需要操作。

我现在正在解决的问题,虽然我预计将来会扩展这个问题,但我有一个加密的标头进入我的应用程序,我想要在控制器中解密,然后在途中再次加密进行。

编辑:为清楚起见。

我有一个休息控制器,例如:

    @RestController
        public class PojoService {
            @GetMapping(value = "/path/to/resource")
                public ResponseEntity<SomeClass> getLocationData(
@RequestHeader(value = "EncryptedHeader", required = false) String ecryptedHeaderValue) {
                    DecryptionObject decryptedHeader = new DecryptionObject(pageHeaderValue);
                    SomePojo result = getResult();
                    return decryptedHeader.decorateResponseWithEncryptedHeader(result);
                }
    }

我希望在每个映射上都没有DecryptionObject,而是在我进入映射之前,我通过一些过滤器或钩子解密头,然后在出路时重新加密头。然后我的代码看起来像:

    @RestController
        public class PojoService {
            @GetMapping(value = "/path/to/resource", decryptHeader="EncryptedHeader")
                public ResponseEntity<SomeClass> getLocationData(
@RequestHeader(value = "EncryptedHeader", required = false) String decryptedHeaderValue) {
                    SomePojo result = getResult();
                    return result;
                }
    }

我发现HandlerInterceptor不起作用,因为我无法修改拦截器中的请求或响应。希望澄清这个问题。

2 个答案:

答案 0 :(得分:2)

您仍然可以使用HandlerInterceptor。创建实现HandlerInterceptor(或扩展HandlerInterceptorAdapter)的类,然后使用另一个扩展WebMvcConfigurer的类来注册它。

@EnableWebMvc
@Configuration
@ComponentScan
public class MyWebConfig implements WebMvcConfigurer {
    public void addInterceptors(InterceptorRegistry registry) {
         registry.addInterceptor(new [...]); //Apply to all controllers
         registry.addInterceptor(new [...]).addPathPatterns("path1","path2"); //Apply to specific paths to restrict to some controllers.
    }
}

您也可以使用过滤器 - 创建您的Filter类并通过声明类型为FilterRegistrationBean的@Bean来注册它 - 这也允许您限制某些路径。

更新:您可以使用可以由拦截器request.setAttribute("decryptedHeaderValue",<decrypted>)设置的请求属性来执行此操作。或者如果您具体使用标头,过滤器将更适合您的目的。创建一个新的包装请求类型,它包装传入的请求并执行您想要的任何操作,并将此包装器传递给链中的下一个过滤器。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
    [...]
    HttpServletRequestWrapper decryptedRequest = new HttpServletRequestWrapper((HttpServletRequest) request) {
       public String getHeader(String name) {
            if (name.equals("DecryptedHeader")) {
                  String encrypted = super.getHeader("EncryptedHeader");
                  String decrypted = decrypt(encrypted);
                  return decrypted;
            }
            return super.getHeader(name); //Default behavior
       }
   }


   chain.doFilter(decryptedRequest, response); //Pass on the custom request down
}

然后任何类下线(其他过滤器,控制器等)都可以调用request.getHeader("DecryptedHeader")来检索解密的标头。这只是许多类似方法中的一种。您可以在注册时限制此过滤器执行的路径。

对于响应,有一个类似的HttpServletResponseWrapper类,您可以使用它来进行自定义。

答案 1 :(得分:0)

我们可以通过interceptor中的addingAttribute来实现

httpServletRequest.setAttribute(,);