• 【跨端】axios发送两次请求原因及解决方法


    最近Vue项目中使用axios组件,在页面交互中发现axios会发送两次请求,一种请求方式为OPTIONS,另外一种为自己设置的。

    什么是CORS通信?

      CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

      CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

      实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨域通信。详情见:前后分离调用API接口跨域问题

    CORS两种请求

      浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

      只要同时满足以下两大条件,就属于简单请求。

    (1) 请求方法是以下三种方法之一:

    • HEAD
    • GET
    • POST

    (2)HTTP的头信息不超出以下几种字段:

    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

      凡是不同时满足上面两个条件,就属于非简单请求。

      非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json

      非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

      浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

      浏览器对这两种请求的处理,是不一样的。

    两次请求原因

      前后端未满足“同源策略/SOP”,俗称请求跨域。浏览器一旦发现请求跨域,就会使用CORS通信,自动添加一些附加的头信息,简单请求只会有一次请求,只有非简单请求会附加一次请求。 

    解决方法

      服务期端直接通过“预检”请求,服务器新建拦截器,拦截所有请求,筛选所有Requset Method:OPTIONS的请求,不做任何处理直接返回即可。

    以下是JAVA设置:

    package com.yhzy.zytx.jwt.Interceptor;
    
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.lang.reflect.Method;
    
    /**
     * @ClassName JwtInterceptor
     * @Description JWT拦截器
     * @Author 天生傲骨、怎能屈服
     * @Date 2019/5/22 13:48
     * @Version 1.0
     */
    public class JwtInterceptor implements HandlerInterceptor {
        
    
        private final static Logger logger = LoggerFactory.getLogger(JwtInterceptor.class);
    
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
            // 从 http 请求头中取出 token
            String token = httpServletRequest.getHeader("Authorization");
    
            // 如果不是映射到方法直接通过
            if(!(object instanceof HandlerMethod)){
                return true;
            }
            HandlerMethod handlerMethod=(HandlerMethod)object;
            Method method=handlerMethod.getMethod();
    
            // OPTIONS请求类型直接返回不处理
            if ("OPTIONS".equals(httpServletRequest.getMethod())){
                return false;
            }
            
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest httpServletRequest,
                               HttpServletResponse httpServletResponse,
                               Object o, ModelAndView modelAndView) throws Exception {
    
        }
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest,
                                    HttpServletResponse httpServletResponse,
                                    Object o, Exception e) throws Exception {
        }
    }

    转载:https://www.cnblogs.com/itmrzhang/p/11003474.html

  • 相关阅读:
    centos8.2安装Rabbitmq-3.8.12
    绝对好文C#调用C++DLL传递结构体数组的终极解决方案
    c++到c#数据类型的转换
    WPF中timer的使用
    接收Dialog的值
    WPF子界面向父界面传递带参数的委托
    2015上海居住证和积分办理流程
    Discuz! X3.2重置管理员账号
    winServer2008下安装SqlServer2008数据库
    jodd cache实现缓存超时
  • 原文地址:https://www.cnblogs.com/vickylinj/p/15002563.html
Copyright © 2020-2023  润新知