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

一、什么是跨域

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

具体能够查看下表:web

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

二、springboot如何解决跨域问题

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

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

说明: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请求呢?springboot

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

缘由

浏览器会在发送真正请求以前,先发送一个方法为OPTIONS的预检请求 Preflighted requests 这个请求是用来验证本次请求是否安全的,可是并非全部请求都会发送,须要符合如下条件:mvc

  • 请求方法不是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的跨域请求

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

(点击文字可跳转)

1. 深究Spring中Bean的生命周期

2. 深刻SpringBoot核心注解原理

3.线上环境部署概览

4.Springboot Vue shiro 实现先后端分离、权限控制

相关文章
相关标签/搜索