java 自定义 headers_Springboot如何优雅的解决ajax+自定义headers的跨域请求

点击上方“Java知音”,选择“置顶公众号”

技术文章第一时间送达!

1、什么是跨域

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

具体可以查看下表:

0080884ca021cfdc203974b1f519e52c.png

2、springboot如何解决跨域问题

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

①请求接口添加注解@CrossOrigin(origins = "http://127.0.0.1:8020", maxAge = 3600)

说明:origins = "http://127.0.0.1:8020" 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请求呢?

f4a27f15ca8c77cf7f2758f122fd8fc6.png

原因

浏览器会在发送真正请求之前,先发送一个方法为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下的。

具体代码实现:

@Componentpublic 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 。

具体代码实现:

@Componentpublic class MyWebConfiguration extends WebMvcConfigurationSupport{    @Resource    private RequestFilter requestFilter;    @Override    public void addInterceptors(InterceptorRegistry registry){        // 跨域拦截器        registry.addInterceptor(requestFilter).addPathPatterns("/**");    }}

4420c8e1f269cf77c73523e41f3bd642.png

此时我们就完美解决了ajax+自定义headers的跨域请求了,欢迎随时交流学习。

推荐阅读(点击文字可跳转)

看完本文有收获?请转发分享给更多人

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值