js跨域的研究

简介: 在开发中总是会遇到,接入层可能去调用其它域名下服务的api,crud数据,可是在这中间会出现js的同源策略,导致同一个DOM不能用多个源加载数据,已确保安全性。 在数据远程调用的设计时候,要考虑性能又要考虑安全性,下边为总结的跨域三种实现: 1:使用ACAO(‘Access-Control-Allow-Origin’)设置响应头域名访问-->问题低版本的ie(10及以下)和个

在开发中总是会遇到,接入层可能去调用其它域名下服务的api,crud数据,可是在这中间会出现js的同源策略,导致同一个DOM不能用多个源加载数据,已确保安全性。

在数据远程调用的设计时候,要考虑性能又要考虑安全性,下边为总结的跨域三种实现:

1:使用ACAO(‘Access-Control-Allow-Origin’)设置响应头域名访问-->问题低版本的ie(10及以下)和个别浏览器并不支持。
2:使用jsonp实现跨域数据请求,可以但是,所有的请求会过滤成GET请求,如果安全数据的读写,有不安全因素。
3:使用form表单提交+target属性指向iframe中代码解析,可以处理,“稍微”有点麻烦。
测试添加配置本地的host:C:\Windows\System32\drivers\etc\HOSTS

10.1**.11.76 www.baidux.com
10.1**.11.76 www.alibabax.com

1:ACAO

服务器(spring-mvc):

①:配置web.xml,过滤所有的*.json或自定义其他结尾的请求:

	<filter>
		<description>js跨域</description>
		<filter-name>JsCrossDomainFilter</filter-name>
		<filter-class>cn.***.filter.JsCrossDomainFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>JsCrossDomainFilter</filter-name>
		<url-pattern>*.json</url-pattern>
	</filter-mapping>
②:cn.***.filter.JsCrossDomainFilter实现代码:

package cn.***.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.module.util.NetworkUtil;

/**
 * js跨域设置过滤器
 * @author Tony_tian
 *  过滤:1:请求浏览器类型记录,js跨域设置
 *  	2:为了不多余设置其他请求,此过滤器只过滤:*.json结尾的请求
 *  注:浏览器兼容注解:
 *  	a:大概在iex~10浏览器:
 *  	 ①:Ajax的error打印出来提示no transport:解决:js中第一行加入即可:jQuery.support.cors = true; 
 *  	 ②:error没有权限:IE浏览器的安全性设置问题:
 *  		解决:点击IE浏览器的的“工具->Internet 选项->安全->自定义级别”将“其他”选项中的“通过域访问数据源”选中为“启用”或者“提示”,点击确定就可以了。
 * */
public class JsCrossDomainFilter implements Filter{
	//日志
	private static final Logger LOG = LoggerFactory.getLogger(JsCrossDomainFilter.class);
	@Override
	public void destroy() {
		
	}
	
	@Override
	public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		String type = NetworkUtil.getBrowser(request);
		NetworkUtil.setJsCrossDomain(type, response);
		LOG.info("请求浏览器类型:" + type + "---> js跨域已设置");
		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		
	}
}
③:NetworkUtil实现代码:

package com.module.util;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.util.StringUtils;
/**
 * 获取请求地址, ip地址
 * @author Administrator
 *
 */
public class NetworkUtil {
	

	public static String getCurrentURL( HttpServletRequest request ) {
		StringBuffer url = new StringBuffer( );
		String appName = request.getContextPath( );

		if ( appName != null && appName.trim( ).length( ) > 0 && !appName.trim( ).equals( "/" ) )
			url.append( appName );
		String page = request.getServletPath( );
		if ( page != null )
			url.append( page );
		String queryString = request.getQueryString( );
		if ( queryString != null )
			url.append( "?" + queryString );

		return url.toString( );
	}

	public static String getIpAddr( HttpServletRequest request ) {
		 String ip = request.getHeader("X-Forwarded-For");
         if(!StringUtils.isEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
             //多次反向代理后会有多个ip值,第一个ip才是真实ip
             int index = ip.indexOf(",");
             if(index != -1){
                 return ip.substring(0,index);
             }else{
                 return ip;
             }
         }
         ip = request.getHeader("X-Real-IP");
         if(!StringUtils.isEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
             return ip;
         }
         return request.getRemoteAddr();

	}
	
	public static String getBrowser(HttpServletRequest request){
		String userAgent = request.getHeader("user-agent");
		if(userAgent.contains("MSIE")){
			return "ie";
		}else if(userAgent.contains("Firefox")){
			return "firefox";
		}else if(userAgent.contains("Chrome")){
			return "chrome";
		}else if(userAgent.contains("Safari")){
			return "safari";
		}else if(userAgent.contains("Opera")){
			return "opera";
		}
		return "other";
	}
	
	/**
	 * 服务器端设置js请求跨域。<br>
	 * 注:javascript的同源策略:同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。
	 *    如果它们的协议、端口(如果指明了的话)和主机名都相同。则他们属于同源。
	 *    简单说:浏览器限制脚本只能和同协议、同域名、同端口的脚本进行交互。<br>
	 * 注: 由于IE8-IE10不支持通过设置Access-Control-Allow-Origin头的方式,所以对于IE需要按照IE提供的方案使用XDomainRequest对象解决。<br>
	 *	      备注:http://msdn.microsoft.com/en-us/library/ie/cc288060(v=vs.85).aspx <br>
	 *	      在使用此方法时在后端为了安全起见最好设置允许那些域进行跨域访问,如“shop.weibaobei.com",多个域名直接用“,”分开
	 * 注:addHeader()方法用指定的值添加 HTML标题。该方法常常向响应添加新的 HTTP标题。它并不替代现有的同名标题。一旦标题被添加,将不能删除。
	 * @author Tony_tian
	 * @param type 如:request.getParameter("type"); request 代表客户端http请求信息对象
	 * @param response 代表服务器端http响应信息对象
	 * */
	public static final void setJsCrossDomain(String type, HttpServletResponse response){
		if("IE".equalsIgnoreCase(type)){
			//对于IE需要按照IE提供的方案使用XDomainRequest对象解决
			response.addHeader("XDomainRequestAllowed", "1");
		}else{
			//'*'表示允许所有域名访问,可以设置为指定域名访问,多个域名中间用','隔开
			response.addHeader("Access-Control-Allow-Origin", "*");
		}
	}
}
注:可配置更详细:

response.addHeader( "Access-Control-Allow-Origin", "*" ); 
response.addHeader( "Access-Control-Allow-Methods", "POST" ); 
response.addHeader( "Access-Control-Max-Age", "1000" );
注:可以在ajax请求中多加入一个参数:

 $.ajax({
            url: "yoururl.json",
            type: "POST",
            crossDomain: true, //这个参数--未测试
            data: data,
            dataType: "json",
            success:function(result){
                alert(JSON.stringify(result));
            },
            error:function(xhr,status,error){
                alert(status);
            }
        });

2:jsonp

ajax代码:

function registerxx(){
	var https_url_ts = "http://www.baidux.com:8080/timespacexstar/";
	var timestamp = (new Date()).valueOf(); 
	$.ajax({
		url: https_url_ts + "registerjsonp.json?timestamp=" + timestamp, //请求url
		type: "post", //http请求方式
		data:{"kaka" : "iamkaka"}, //序列化表单---data:$("#registerform").serialize(),
		async: true, //ajax请求是异步的
		dataType: "jsonp", //返回数据类型jsonp格式
		timeout: 60000, //请求超时时间
		jsonp: "jsonpcallbackfunction",//服务端用于接收callback调用的function名的参数 
		jsonpCallback: "success_jsonpCallback",//callback的function名称,服务端会把名称和data一起传递回来
		success:function(resdata){
		   var code = resdata.code;
		   var message = resdata.message;
		   var data = resdata.data;
		   alert(code + "/" + message + "/" + data);
		}
	});
}
注:页面请求的地址:

http://www.alibabax.com:8080/timespacexstar/register.html

服务器代码(spring-mvc):

import com.fasterxml.jackson.databind.util.JSONPObject;
	@ResponseBody
	@RequestMapping(value = "registerjsonp", produces = "application/json; charset=UTF-8")
	public JSONPObject registerCT(Member registerParamsC, String jsonpcallbackfunction, HttpServletRequest request){
		JsonResult json = new JsonResult();
		String kaka = request.getParameter("kaka");
		LOG.info("注册html信息数据记录111:" + jsonpcallbackfunction + " |~| " + kaka + " // " + request.getRequestURI() + "==" + request.getQueryString());
		json.setCode(JsonResult.CODE_WARMTIPS);
		json.setData("success-ok" + kaka);
		json.setMessage("successful!!!");
		JSONPObject jsonp = new JSONPObject(jsonpcallbackfunction, json);
		return jsonp;
	}

注:页面效果:



后台日志:

注册html信息数据记录111:success_jsonpCallback |~| iamkaka // /timespacexstar/registerjsonp.json==timestamp=1458791397407&jsonpcallbackfunction=success_jsonpCallback&kaka=iamkaka&_=1458791396313

3:form表单提交+target属性指向iframe中代码解析http://msdn.microsoft.com/en-us/library/ie/cc288060(v=vs.85).aspx

备注:

IE需要按照IE提供的方案使用XDomainRequest对象解决//////效果不佳

js跨域及解决方案

How to make a jsonp POST request that specifies contentType with jQuery?

相关实践学习
基于函数计算快速搭建Hexo博客系统
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
目录
相关文章
|
4月前
|
JavaScript 索引
用原生js的postMessage实现iframe传值,也可以用于跨域嵌套iframe传值
用原生js的postMessage实现iframe传值,也可以用于跨域嵌套iframe传值
用原生js的postMessage实现iframe传值,也可以用于跨域嵌套iframe传值
|
1月前
|
JavaScript 安全 前端开发
js开发:请解释什么是跨域请求(CORS),以及如何解决跨域问题。
CORS是一种W3C标准,用于解决浏览器同源策略导致的跨域数据访问限制。它通过服务器在HTTP响应头添加标志允许特定源进行跨域请求。简单请求无需预检,而预检请求(OPTIONS)用于询问服务器是否接受非简单请求。服务器端配置响应头如`Access-Control-Allow-Origin`等实现CORS策略,客户端JavaScript则正常发起请求。若配置不当,浏览器将阻止跨域访问,保障安全。
23 2
|
4月前
|
前端开发 JavaScript 安全
JavaScript高级主题:什么是跨域资源共享(CORS)?
JavaScript高级主题:什么是跨域资源共享(CORS)?
40 0
|
4月前
|
JSON JavaScript 前端开发
JS解决跨域问题
JS解决跨域问题
32 0
|
5月前
|
自然语言处理 JavaScript 前端开发
【Vue.js】使用Element入门搭建登入注册界面&axios中GET请求与POST请求&跨域问题
【Vue.js】使用Element入门搭建登入注册界面&axios中GET请求与POST请求&跨域问题
166 0
|
6月前
|
JavaScript
vue-cli3.0无config,js跨域解决
vue-cli3.0无config,js跨域解决
24 2
|
6月前
|
JSON JavaScript 前端开发
js如何解决跨域问题?
js如何解决跨域问题?
65 0
|
7月前
|
前端开发 JavaScript
js - 前端跨域
端口号范围 0 ~ 65535
|
8月前
|
JavaScript 前端开发
js处理跨域问题
在JS中,跨域指的是在浏览器中使用Ajax等方式向其他域名的服务器请求数据时出现跨域问题,导致请求失败或数据无法返回的问题。为了解决这个问题,可以采用以下方法:
71 0
|
8月前
|
JavaScript 前端开发 API
js中的跨域
js中的跨域
52 0