因为浏览器同源策略(同源策略,它是由Netscape提出的一个著名的安全策略。如今全部支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。),凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不一样即为跨域。java
具体能够查看下表:web
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
浏览器会在发送真正请求以前,先发送一个方法为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("/**"); } }
此时咱们就完美解决了ajax+自定义headers的跨域请求了,欢迎随时交流学习。
推荐阅读(点击文字可跳转)
3.线上环境部署概览