修改进入控制器的请求 header 和响应 header 离开 Spring Boot RestController
Modify request header going into a controller and response header leaving a Spring Boot RestController
这感觉应该是一件简单的事情,但我对 SpringBoot 和整个 Servlet 生态系统还是很陌生,所以它不是很明显。我喜欢类似于 HandlerInterceptor 的接口,它允许我在控制器中完成后修改请求和响应 object。更好的方法是装饰映射注释,这样我就可以指定哪些控制器需要操作。
我现在正在解决的问题是,虽然我预计将来会扩展这个问题,但我有一个加密的 header 进入我的应用程序,我想解密它以便在控制器中使用,并且然后在出路时再次加密。
编辑:为清楚起见。
我有一个休息控制器,比如:
@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,而是在我开始映射之前,我通过一些过滤器或钩子解密 header 然后 re-encrypt header 出去的路上。然后我的代码看起来像:
@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 不起作用,因为我无法在拦截器中修改请求或响应。希望能澄清问题。
您仍然可以使用 HandlerInterceptor。创建您的 class 实现 HandlerInterceptor(或扩展 HandlerInterceptorAdapter),然后使用扩展 WebMvcConfigurer.
的另一个 class 注册它
@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.
}
}
您也可以使用过滤器来做到这一点 - 创建您的过滤器 class 并通过声明类型为 FilterRegistrationBean 的 @Bean
来注册它 - 这也允许您限制某些路径。
更新:您可以使用可由拦截器设置的请求属性来执行此操作(request.setAttribute("decryptedHeaderValue",<decrypted>)
。或者,如果您具体使用 headers,过滤器将更适合您的目的。创建一个新的包装请求类型来包装传入的请求并执行您想要的任何操作,并将此包装器传递给链中的下一个过滤器。
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
}
然后任何 class 下线(其他过滤器、控制器等)都可以调用 request.getHeader("DecryptedHeader")
来检索解密的 header。这只是许多类似方法中的一种。您可以在注册时限制此过滤器执行的路径。
对于响应,有一个类似的 class HttpServletResponseWrapper,您可以使用它来进行自定义。
我们可以通过在 interceptor
中添加属性来做到这一点
httpServletRequest.setAttribute(,);
这感觉应该是一件简单的事情,但我对 SpringBoot 和整个 Servlet 生态系统还是很陌生,所以它不是很明显。我喜欢类似于 HandlerInterceptor 的接口,它允许我在控制器中完成后修改请求和响应 object。更好的方法是装饰映射注释,这样我就可以指定哪些控制器需要操作。
我现在正在解决的问题是,虽然我预计将来会扩展这个问题,但我有一个加密的 header 进入我的应用程序,我想解密它以便在控制器中使用,并且然后在出路时再次加密。
编辑:为清楚起见。
我有一个休息控制器,比如:
@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,而是在我开始映射之前,我通过一些过滤器或钩子解密 header 然后 re-encrypt header 出去的路上。然后我的代码看起来像:
@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 不起作用,因为我无法在拦截器中修改请求或响应。希望能澄清问题。
您仍然可以使用 HandlerInterceptor。创建您的 class 实现 HandlerInterceptor(或扩展 HandlerInterceptorAdapter),然后使用扩展 WebMvcConfigurer.
的另一个 class 注册它@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.
}
}
您也可以使用过滤器来做到这一点 - 创建您的过滤器 class 并通过声明类型为 FilterRegistrationBean 的 @Bean
来注册它 - 这也允许您限制某些路径。
更新:您可以使用可由拦截器设置的请求属性来执行此操作(request.setAttribute("decryptedHeaderValue",<decrypted>)
。或者,如果您具体使用 headers,过滤器将更适合您的目的。创建一个新的包装请求类型来包装传入的请求并执行您想要的任何操作,并将此包装器传递给链中的下一个过滤器。
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
}
然后任何 class 下线(其他过滤器、控制器等)都可以调用 request.getHeader("DecryptedHeader")
来检索解密的 header。这只是许多类似方法中的一种。您可以在注册时限制此过滤器执行的路径。
对于响应,有一个类似的 class HttpServletResponseWrapper,您可以使用它来进行自定义。
我们可以通过在 interceptor
httpServletRequest.setAttribute(,);