JS跨域两三事
今日,前端开发要求新的Web服务需要支持跨域,因为要发起 Ajax 到后端web 服务域名请求数据;
前端application域名是 other.abc.com (举个栗子) api接口域名是 another.abc.com。
后端web application是SpringMVC开发,于是,我在web.xml 配置了新Filter。
Filter代码是这样:
1 public class CrossDomainFilter implements Filter { 2 3 private static final Logger logger = LoggerFactory.getLogger(CrossDomainFilter.class); 4 5 @Override 6 public void init(FilterConfig filterConfig) throws ServletException { 7 8 } 9 10 @Override 11 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 12 HttpServletRequest req = (HttpServletRequest) request; 13 14 15 String originDomain = req.getHeader("origin"); 16 17 String[] hostSplit = StringUtils.split(originDomain, "."); 18 String subDomain = null != hostSplit && hostSplit.length >= 2 ? hostSplit[hostSplit.length - 2] + "." + hostSplit[hostSplit.length - 1] : null; 19 20 if (StringUtils.isNotEmpty(originDomain) && StringUtils.isNotEmpty(subDomain) && subDomain.equals("abc.com")) { 21 // 允许js 跨域 22 HttpServletResponse res = (HttpServletResponse) response; 23 res.setHeader("Access-Control-Allow-Origin", originDomain); 24 res.setHeader("Access-Control-Allow-Credentials", "true"); 25 res.setHeader("Access-Control-Allow-Methods", "*"); 26 res.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type"); 27 } 28 chain.doFilter(request, response); 29 30 } 31 32 @Override 33 public void destroy() { 34 35 } 36 }
开发完成后我本地写一个简单的页面做测试,是一个php编写的Web页面,一开始是这样的:
1 <html> 2 3 <head> 4 <title>前端页面 - js跨域local测试</title> 5 <script src="https://cdn.bootcss.com/jquery/3.2.1/core.js"></script> 6 </head> 7 8 <body> 9 10 <a href="javascript:;" class="do_request">请求</a> 11 12 <script type="text/javascript"> 13 $(function () { 14 $(".do_request").on("click", function () { 15 console.log("request sent!"); 16 17 $.ajax({ 18 19 url: "http://another.abc.com:8080/geo/gpsconvert", 20 data: { 21 "_gps":"120,30" 22 }, 23 24 success: function (res) { 25 alert(res.succ); 26 }, 27 dataType: "jsonp" 28 }); 29 30 }); 31 }); 32 </script> 33 </body> 34 </html>
本地点击发 Ajax 请求给后端接口,发现 req.getHeader("origin") 这个返回总是 null,百思不得其解,
经过前端提示得知,发送ajax 请求必须按照下面:
1 $.ajax({ 2 crossDomain: true, 3 url: "http://another.abc.com:8080/geo/gpsconvert", 4 data: { 5 "_gps":"120,30" 6 }, 7 8 success: function (res) { 9 alert(res.succ); 10 11 }, 12 dataType: "json" 13 });
服务端的 origin 才能拿到 请求发起方的host,jsonp 不是真正的CORS!而是一种跨域trick,另外
jsonp 只支持GET!
设置 crossDomain: true 后,服务端 origin 正常。
对PHP 来说,只要一行代码:
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : null;
此外,Access-Control-Allow-Origin 的值谁请求上来给谁设置Response Header 即可。不建议设置 为 Access-Control-Allow-Origin: *
这样相当于所有请求的域都允许跨域了,显然不大合适。