淘先锋技术网

首页 1 2 3 4 5 6 7
function https(url,type,data,header,callback) {
    $.ajax({
        url:url,
        type:type,
        data:data,
        contentType:'application/json',
        headers:header,
        crossDomain:true,
        success:function (data,status) {
            console.log(data);
            if(data.errorNo == "20001" || data.errorNo == "20002"){
            //令牌失效
                window.location.href = "./lyear_pages_login.html";
            }else if(data.errorNo == "0"){
                callback(data,status);
            }else{
                alert(data.errorInfo);
            }
        },
        error:function (XMLHttpRequest,textStatus,errorThrown) {
            if(textStatus==='timeout'){
                alert('請求超時');
                setTimeout(function(){
                    alert('重新请求');
                },2000);
            }
            window.location.href = "./lyear_pages_login.html";
        }
    })
}

使用改模板发送一个请求到本地服务器的时候,会出现以下的错误:403

General:
Request URL: http://localhost:9090/....
Request Method: OPTIONS
Status Code: 403 
Remote Address: [::1]:9090
Referrer Policy: no-referrer-when-downgrade

Response Headers:
Connection: keep-alive
Date: Sat, 28 Mar 2020 07:12:49 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunked
Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers

Request Headers:
Provisional headers are shown
Access-Control-Request-Headers: authentication,content-type
Access-Control-Request-Method: GET
Origin: http://localhost:63342
Referer: http://localhost:63342/lyear_2_LightYear-admin/index.html
Sec-Fetch-Mode: cors
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36

可以看到这个请求是OPTIONS的,而不是我们预期的GET或是POST。

原因在于:https://www.cnblogs.com/wanghuijie/p/preflighted_request.html

也就是这是一个Preflighted Request,所以发送真正的请求之前会发送一个OPTIONS请求用于试探服务器是否能接受真正的请求。如果options获得的回应是拒绝性质的,比如404\403\500等http状态,就会停止post、get等请求的发出。

关于Preflighted Request(带预检的跨域请求)发生在:

(文档地址:https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#The_HTTP_request_headers)

  1. 请求方法不是GET/HEAD/POST
  2. POST请求的Content-Type并非application/x-www-form-urlencodedmultipart/form-data, 或text/plain
  3. 请求设置了自定义的header字段

以上封装的请求符合了2和3。而且在使用token验证和大量json数据的请求中是不可避免的。

解决方法:给OPTIONS请求一个正确的响应。

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authenticationInterceptor())
                .addPathPatterns("/**");
    }

    /**
    *@Author: Czc on 2020/3/28 14:18
    *@param:
    *@return:
    *@Description: 跨域请求配置
    **/
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
                .maxAge(3600)
                .allowCredentials(true);
    }
    @Bean
    public AuthenticationInterceptor authenticationInterceptor() {
        return new AuthenticationInterceptor();
    }
}

addCorsMappings方法对OPTIONS方法返回了允许的响应。

options请求

然后再发出真正的请求。

real request 当然,就像登陆校验拦截器一样,也可以通过拦截器对请求进行处理,再响应的报文头部中加上跨域请求相关的字段。然后对于OPTIONS请求直接截断返回。其他的请求继续进行。