全国服务热线:4008-888-888

技术知识

微信小程序源码下载_Javascript完成跨域后台设置拦

Javascript实现跨域后台设置拦截的方法详解     .Miao   这篇文章主要给大家介绍了关于Javascript实现跨域后台设置拦截的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面跟着小编来一起学习学习吧。

本文主要给大家介绍了关于Javascript跨域后台设置拦截的相关内容,分享出来供大家参考学习,话不多说了,来一起看看详细的介绍吧。

子域名之间互相访问需要跨域

结论放在开头:

1.服务端必须设置允许跨域

2.客户端带cookie需要设置 withCredentials

3.无论服务端是否允许跨域,该request都会完整执行

4. options 预请求需要设置返回空,不然requestMapping没有支持该方法则出错

环境搭建

需求

首先需要搭建两个环境。一个是提供API的server A,一个是需要跨域访问API的server B。

Server A提供了一个api。完整的请求request是:

contentmain/getDepositsRoomAndRatePlanInfo.json htid=759 _=18

Server B有个页面page:
<

并且这个page需要请求server A的api。

但由于跨域保护,请求失败:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'xxxxx' is therefore not allowed access.

修改host

首先本地配置两个指向127.0.0.1的host,方便互相跨域。

127.0.0.1 .net 
127.0.0.1 .net

启动项目A,方便提供API。
<,并通过一个工具发布:

 browser-sync 

安装

npm install -g browser-sync
<
" --host ".net" --port 3001

关于跨域CORS

ruanyifeng 的文章里说浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

其中同时满足一下2种标准即为简单跨域:

1) 请求方法是以下三种方法之一:
HEAD POST

2)HTTP的头信息不超出以下几种字段:
Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

而其他情况,非简单请求是那种对服务器有特殊要求的请求,比如请求方法是  PUT 或 DELETE ,或者 Content-Type 字段的类型是 application/json 。非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight),即 options 请求。

关键

跨域的关键是浏览器获得服务器的认可,而服务器的认可就是header里的 Access-Control-Allow-Origin 。浏览器通过比较服务端返回的response中是否包含这个字段,以及包含这个字段的内容是否是当前网址来确定是否跨域。也就是说绕过浏览器是可以不用跨域的。

有个问题,看好多文章并没有指出。

第一点,带cookie问题。浏览器设置 withCredentials 为 true 则会带cookie发送给服务端。而服务端设置 Access-Control-Allow-Credentials 为 true 则接收, false 则不接受。关键是到filter里的时候才会决定是否设置response,那么这时候cookie已经存在request里了吧。(待验证)

验证:server端确实已经接受了cookie,即使设置为false,服务端仍旧接受cookie。而客户端也仍旧可以发送cookie。

第二点,简单跨域中,浏览器的请求直接发送给服务器,服务器返回是否支持跨域(即是否header加origin), 那么简单跨域究竟是请求了服务端几次?如果是1次,那么如果服务端不支持跨域,即没有设置allow,还会不会继续走下去,会不会继续request得到结果后放入response?就是不论跨域不跨域服务器是否都会执行这个request对应的计算。因为所有的设置header都是给浏览器告知的,和服务端限制无关。(待验证)

验证:即使服务端没有设置允许跨域,当客户端请求过来时,服务端仍旧完整执行了请求并返回,只是客户端没有接收。

服务端需要做点工作

针对上述两种跨域。server A需要写一个filter。

 filter 
 filter-name cors /filter-name 
 .test.filter.CorsFilter /filter-class 
 /filter 
 filter-mapping 
 filter-name cors /filter-name 
 url-pattern /* /url-pattern 
 /filter-mapping 
 /filter 

Filter:

public class CorsFilter extends OncePerRequestFilter {
 @Override
 protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
 throws ServletException, IOException {
 URL requestURL = new URL(request.getRequestURL().toString());
 String hostName = requestURL.getHost();
 String origin = request.getHeader("Origin");
 int index = hostName.indexOf(".");
 if(index -1) {
 String domainHost = hostName.substring(index, hostName.length());
 if(!StringUtils.isEmpty(origin) origin.contains(domainHost)) {
 response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
 response.addHeader("Access-Control-Allow-Origin", origin);
 response.addHeader("Access-Control-Allow-Credentials", "true");
 response.setHeader("Access-Control-Max-Age", "3600");
 response.addHeader("Access-Control-Allow-Headers", "Content-Type, Cookie, " +
 "Accept-Encoding, User-Agent, " +
 "Host, Referer, " +
 "X-Requested-With, Accept, " +
 "Accept-Language, Cache-Control, Connection");
 if (request.getHeader("Access-Control-Request-Method") != null "OPTIONS".equals(request.getMethod())) {
 // CORS "pre-flight" request
 response.setStatus(200);
 return;
 filterChain.doFilter(request, response);
}

上述filter是为了同一个domain下,不同子域名可以跨域访问,而其他domain则不可以,因为我们需要共享cookie,所以设置 Access-Control-Allow-Credentials 为 true . 如果设置为 false 则不接受cookie。

客户端,即server B如果想要发送cookie则需要设置 withCredentials 为 true .

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
//jquery
$.ajax({
 xhrFields: {
 withCredentials: true
});

注意:针对非简单跨域的时候发送 options 请求,服务端A需要告诉浏览器是否支持跨域即可,不要往下走了,不然到指定的requestMapping发现不支持这个方法就会很尴尬了,所以直接返回。

下面针对简单跨域和非简单跨域做测试:

 !DOCTYPE html 
 html lang="en" 
 meta charset="UTF-8" 
 title test /title 
 script src="jquery-1.11.3.js" /script 
 /head 
 body 
 input type="button" value="GET_Default" 
 input type="button" value="GET_JSON" 
 input type="button" value="POST_Default" 
 input type="button" value="POST_JSON" 
 input type="button" value="PUT" 
 script 
 var getUrl = "contentmain/getDepositsRoomAndRatePlanInfo.json htid=759";
 var postUrl = "contentmain/saveReservationDeposits.json htid=759";
 function testGetDefault(){
 sendAjax("GET",getUrl, "json", "application/x-www-form-urlencoded");
 function testGetJSON(){
 sendAjax("GET",getUrl, "json", "application/json; charset=utf-8");
 function testPostDefault(){
 sendAjax("POST",postUrl, "json", "application/x-www-form-urlencoded");
 function testPostJson(){
 sendAjax("POST",postUrl, "json", "application/json; charset=utf-8");
 function testPUT(){
 sendAjax("PUT",postUrl, "json", "application/json; charset=utf-8");

dataType : dataType, // accept type contentType: contentType, //request type, default is application/x-www-form-urlencoded success: function(result){ console.log(result); error: function (xhr) { console.log(xhr);
General: Request URL:contentmain/getDepositsRoomAndRatePlanInfo.json htid=759 Request Method:OPTIONS Status Code:200 OK Remote Address:127.0.0.1:8443 Response Headers: Access-Control-Allow-Credentials:true Access-Control-Allow-Headers:Content-Type, Cookie, Accept-Encoding, User-Agent, Host, Referer, X-Requested-With, Accept, Accept-Language, Cache-Control, Connection Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS Access-Control-Allow-Origin:1.1 Request Headers: Accept:*/* Accept-Encoding:gzip, deflate, sdch, br Accept-Language:zh-CN,zh;q=0.8 Access-Control-Request-Headers:content-type Access-Control-Request-Method:GET Connection:keep-alive Host:.net:8443 Origin:/.net: User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

然后再发送正常的Get请求。

post default:

正常发送请求。

post json: 先发送一个options请求。然后再发送正常的请求。

其他同理,总之,非简单跨域会多发一次options请求来确认是否支持跨域,这时候服务端一定要返回支持跨域,并且直接返回即可。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对凡科的支持。



在线客服

关闭

客户服务热线
4008-888-888


点击这里给我发消息 在线客服

点击这里给我发消息 在线客服