一、问题
使用前后端分离模式开发项目时,往往会遇到这样一个问题 -- 无法跨域获取服务端数据
这是由于浏览器的同源策略导致的,目的是为了安全。在前后端分离开发模式备受青睐的今天,前端和后台项目往往会在不同的环境下进行开发,这时就会出现跨域请求数据的需求,目前的解决方案主要有以下几种:
JSONP、iframe、代理模式、CORS等等
前面几种方式在这里不讲,网上有很多资料。在这里我主要分享一下CORS这种解决方式,CORS即“跨域资源共享”,它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
使用 CORS 跨域的时候和普通的 ajax 过程是一样的,只是浏览器在发现这是一个跨域请求的时候会自动帮我们处理一些事情,所以说只要服务端提供支持,前端是不需要做额外的事情的。
二、实现
实现的大概思路是这样的,首先使用过滤器获取请求对象request的信息,比如Origin 字段(表示请求来自哪个源,包括协议、域名、端口),通过预先配置的参数判断请求是否合法,然后设置响应对象response的头信息,实现跨域资源请求。在介绍实现方式之前我们先来了解一下会用到的响应头信息。
响应头
-
Access-Control-Allow-Methods
用来列出浏览器的CORS请求允许使用的HTTP方法,如:GET、POST、PUT、DELETE、OPTIONS
OPTIONS方法介绍:跨域时,浏览器会先发一次OPTIONS请求:OPTIONS 方法在跨域请求(CORS)中的应用
-
Access-Control-Allow-Credentials
表示是否支持跨域Cookie -
Access-Control-Allow-Headers
逗号分隔的字符串,表示服务器支持的所有头信息字段,如Content-Type以及自定义的字段,前端往后端发送的header头如果未在Access-Control-Allow-Headers配置,则会跨域失败
-
Access-Control-Expose-Headers
与“Access-Control-Allow-Headers”相反,表示不支持的头信息字段 -
Access-Control-Allow-Origin
允许跨域的请求源信息,包括协议、域名、端口,为*
表示允许所有请求来源,服务端会校验前端请求header参数中的Origin参数
spring boot java配置如下:
package com.rh.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class CorsConfig{ @Bean public CorsFilter corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); final CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); // 允许cookies跨域 config.addAllowedOrigin("*");// #允许向该服务器提交请求的URI,*表示全部允许,自定义可以添加多个,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin config.addAllowedHeader("header1");// #允许访问的头信息,*表示全部,可以添加多个 config.setMaxAge(18000L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了 config.addAllowedMethod("OPTIONS");// 允许提交请求的方法,*表示全部允许,一般OPTIONS,GET,POST三个够了 config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); config.addAllowedMethod("PATCH"); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } }
测试页面:里面传入了一个没有被允许的header:header2
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="Generator" content="EditPlus®"> <meta name="Author" content=""> <meta name="Keywords" content=""> <meta name="Description" content=""> <title>prd page</title> <script src="../js/jquery.min.js"></script> <script> $(document).ready(function(){ $.ajax({url:"http://127.0.0.1:8002/test/test2", headers:{"header2":"aaaa"},success:function(result){ $("#div1").html(result); }}); }); </script> </head> <body> <div id="div1"><h2>使用 jQuery AJAX 修改文本内容</h2></div> </body> </html>
会提示跨域失败
备注:跨域只能在html中用ajax测试 不能再postman等测试工具中测试(postman用的是类似于httpclient实现的,而不是ajax方式去请求,所以无法测试跨域问题)
本文参考
https://www.jianshu.com/p/d6dc9e60c8e6
https://blog.csdn.net/puma_dong/article/details/51395976