欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Springboot解决ajax+自定义headers的跨域请求问题

程序员文章站 2023-11-17 11:32:28
1、什么是跨域 由于浏览器同源策略(同源策略,它是由netscape提出的一个著名的安全策略。现在所有支持javascript 的浏览器都会使用这个策略。所谓同源是指,域...

1、什么是跨域

由于浏览器同源策略(同源策略,它是由netscape提出的一个著名的安全策略。现在所有支持javascript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。),凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。

具体可以查看下表:

Springboot解决ajax+自定义headers的跨域请求问题

2、springboot如何解决跨域问题

1.普通跨域请求解决方案:

①请求接口添加注解@crossorigin(origins = "", maxage = 3600)

说明:origins = "" origins值为当前请求该接口的域

②通用配置(所有接口都允许跨域请求)

新增一个configration类 或 在application中加入corsfilter和corsconfiguration方法

@configuration 
public class corsconfig { 
  private corsconfiguration buildconfig() { 
    corsconfiguration corsconfiguration = new corsconfiguration(); 
    corsconfiguration.addallowedorigin("*"); // 1允许任何域名使用
    corsconfiguration.addallowedheader("*"); // 2允许任何头
    corsconfiguration.addallowedmethod("*"); // 3允许任何方法(post、get等) 
    return corsconfiguration; 
  } 

  @bean 
  public corsfilter corsfilter() { 
    urlbasedcorsconfigurationsource source = new urlbasedcorsconfigurationsource(); 
    source.registercorsconfiguration("/**", buildconfig()); // 4 
    return new corsfilter(source); 
  } 
} 

2.ajax自定义headers的跨域请求

$.ajax({
    type:"get",
    url:"http://localhost:8766/main/currency/sgininstate",
    datatype:"json",
    data:{
      uid:userid
    },
    beforesend: function (xmlhttprequest) {
      xmlhttprequest.setrequestheader("authorization", access_token);
    },
    success:function(res){
      console.log(res.code)
    }
  })

此时请求http://localhost:8766/main/currency/sgininstate接口发现options http://localhost:8766/main/currency/sgininstate 500错误,普通跨域的解决方案已经无法解决这种问题,为什么会出现options请求呢?

Springboot解决ajax+自定义headers的跨域请求问题

原因

浏览器会在发送真正请求之前,先发送一个方法为options的预检请求 preflighted requests 这个请求是用来验证本次请求是否安全的,但是并不是所有请求都会发送,需要符合以下条件:

•请求方法不是get/head/post
•post请求的content-type并非application/x-www-form-urlencoded, multipart/form-data, 或text/plain

•请求设置了自定义的header字段

对于管理端的接口,我有对接口进行权限校验,每次请求需要在header中携带自定义的字段(token),所以浏览器会多发送一个options请求去验证此次请求的安全性。

为何options请求是500呢?

options请求只会携带自定义的字段,并不会将相应的值带入进去,而后台校验token字段时 token为null,所以验证不通过,抛出了一个异常。

那么我们现在来解决这种问题:

① spring boot项目application.yml中添加

spring:
mvc:
dispatch-options-request: true

注意:这种解决方案可能在某些情况下并不能解决options问题,原因可能是环境问题,也可能是复杂的自定义filter过滤器配置问题等。

②添加过滤器配置

第一步:手写requestfilter请求过滤器配置类此类需要实现handlerinterceptor类,handlerinterceptor类是org.springframework.web.servlet.handlerinterceptor下的。

具体代码实现:

@component
public class requestfilter implements handlerinterceptor {
  public boolean prehandler(httpservletrequest request,httpservletresponse response,object handler){
    response.setheader("access-control-allow-origin", "*");
    response.setheader("access-control-allow-credentials", "true");
    response.setheader("access-control-allow-methods", "get, head, post, put, patch, delete, options");
    response.setheader("access-control-max-age", "86400");
    response.setheader("access-control-allow-headers", "authorization");
    // 如果是options请求则结束
    if (httpmethod.options.tostring().equals(request.getmethod())) {
      response.setstatus(httpstatus.no_content.value());
      return false;
    }
    return true;
  }
}

第二步:手写mywebconfiguration此类需要继承webmvcconfigurationsupport。

注意:webmvcconfigurationsupport是2.x版本以上的,1.x版本为webmvcconfigureradapter 。

具体代码实现:

@component
public class mywebconfiguration extends webmvcconfigurationsupport{
  @resource
  private requestfilter requestfilter;
  @override
  public void addinterceptors(interceptorregistry registry) {
    // 跨域拦截器
    registry.addinterceptor(requestfilter).addpathpatterns("/**");
  }
}

Springboot解决ajax+自定义headers的跨域请求问题

总结

以上所述是小编给大家介绍的springboot解决ajax+自定义headers的跨域请求问题,希望对大家有所帮助