【问题标题】:OPTIONS request handler should be called before API handlerOPTIONS 请求处理程序应在 API 处理程序之前调用
【发布时间】:2019-09-17 05:58:09
【问题描述】:

我有一个可以工作的 @RestController 组件,它产生 API Web 端点。

这是其中一个端点

  @CrossOrigin
  @GetMapping(API_VERSION + PLAYER + METHOD_FETCH + "/{uid:^[0-9]*$}")
  public Player fetchPlayer(@PathVariable("uid") String uid) {
    return mongoTemplate.findById(uid, Player.class);
  }

现在,当使用我的 Vue.js 应用程序时,我调用了这个端点。问题是axios http 客户端库将具有身份验证标头的 get 请求转换为 options 请求以探测服务器以进行实际访问。

现在我需要使用这个 options 请求并为 CORS 启用它。因此,我做了以下事情:

@RestController
@Log
@RequestMapping("/**")
public class AuthenticationEndpoint {
  @CrossOrigin
  @RequestMapping(method = RequestMethod.OPTIONS)
  public void handleOptionRequest(){
    log.info("option request handled");
  }
}

我将它映射到每个 url,因此它“应该”拦截每个 OPTIONS 请求。但事实并非如此。当有一个

GET http://{{host}}:80/api/v0.1/player/fetch/4607255831
Authorization: Basic MTIzNTM2NDMyNDphYmMxMjM=

更具体的 API Web 端点在 OPTIONS 处理程序之前处理。 我如何才能将 OPTIONS 处理程序放在 Spring MVC 中的其他处理程序之前? 我希望它像拦截器一样工作

实现所需行为的最佳实践方式是什么?我觉得我正在寻找更好的解决方案。

【问题讨论】:

    标签: java spring-boot request cors


    【解决方案1】:

    如何在 Spring MVC 中将 OPTIONS 处理程序放在其他处理程序之前?我希望它起到拦截器的作用。

    你可以创建一个组件一个实现Filter接口的类并给它一个高阶:

    @Component
    @Order(1)
    public class RequestInterceptor implements Filter {
    
        @Override
        public void doFilter
          ServletRequest request, 
          ServletResponse response, 
          FilterChain chain) throws IOException, ServletException {
    
            HttpServletRequest req = (HttpServletRequest) request;
            String httpMethod = req.getMethod();
            if(HttpMethod.OPTIONS.name().equals(httpMethod)){
               //do something here before reaching the method handler
            }
            chain.doFilter(request, response);
    
        }
    
        // other methods 
    }
    

    或者您可以扩展OncePerRequestFilter.java 并在doFilterInternal 方法中进行与上述相同的检查。


    编辑

    如果您想控制是否继续处理捐赠请求,您可以使用HandlerInterceptor

    在适当的 HandlerAdapter 之前调用 HandlerInterceptor 触发处理程序本身的执行。这种机制可以 用于预处理方面的大领域,例如为了 授权检查,或常见的处理程序行为,如语言环境或主题 变化。它的主要目的是允许分解重复 处理程序代码。

    HandlerInterceptor 基本上类似于 Servlet 过滤器,但与后者相比,它只允许自定义 带有禁止执行的选项的预处理 处理程序本身和自定义后处理。过滤器更强大, 例如,它们允许交换请求和响应对象 那些被传递下来的链条。请注意,过滤器在 web.xml,应用程序上下文中的 HandlerInterceptor。

    @Comonent
    public class LoggerInterceptor extends HandlerInterceptorAdapter {
         @Override
         public boolean preHandle(HttpServletRequest request,
                              HttpServletResponse response,
                              Object handler)
                       throws Exception{
             // do checks and decide wether to complete or to stop here
             // true if the execution chain should proceed with the next interceptor or the handler itself. 
            // Else, DispatcherServlet assumes that this interceptor has already dealt with the response itself.
            return true;
         }
         // other methods
    }
    

    【讨论】:

    • 这样吗?看起来也只是一种解决方法。据我了解, OPTIONS 请求它正在探测主机资源是否可以访问。之后返回“真实”状态(?),它将执行真正的 GET 请求。在过滤器中,我不能立即向请求者发回“真”。
    • 不,这不是实现目标的唯一方法,您可以使用 spring HanderInterceptorAdapter,我会更新我的回复
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-26
    • 2017-04-28
    • 1970-01-01
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    相关资源
    最近更新 更多