js跨域的研究

本文涉及的产品
.cn 域名,1个 12个月
简介: 在开发中总是会遇到,接入层可能去调用其它域名下服务的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?

目录
相关文章
|
19天前
|
JSON JavaScript 前端开发
js跨域实现
【10月更文挑战第31天】在实际开发中,需要根据具体的需求和项目情况选择合适的跨域解决方案。
18 1
|
6月前
|
JSON JavaScript 前端开发
【JavaScript技术专栏】JavaScript的跨域通信方法
【4月更文挑战第30天】本文探讨了JavaScript中的跨域通信方法,包括:同源策略和跨域通信的概念,以及JSONP、CORS、WebSockets、`window.postMessage()`、代理服务器和WebAssembly的使用。这些技术各有优劣,适用于不同的场景,是Web开发者解决跨域问题的关键工具。随着Web技术的演进,跨域通信的解决方案也将不断更新。
141 0
|
6月前
|
JavaScript 索引
用原生js的postMessage实现iframe传值,也可以用于跨域嵌套iframe传值
用原生js的postMessage实现iframe传值,也可以用于跨域嵌套iframe传值
用原生js的postMessage实现iframe传值,也可以用于跨域嵌套iframe传值
|
4月前
|
JavaScript
JS【实战】跨域的网页链接跳转
JS【实战】跨域的网页链接跳转
60 0
|
4月前
|
前端开发 JavaScript API
js【详解】ajax (含XMLHttpRequest、 同源策略、跨域、JSONP)
js【详解】ajax (含XMLHttpRequest、 同源策略、跨域、JSONP)
54 0
|
6月前
|
JavaScript Java 测试技术
Java项目基于ssm+vue.js的科研经费管理系统研究附带文章和源代码设计说明文档ppt
Java项目基于ssm+vue.js的科研经费管理系统研究附带文章和源代码设计说明文档ppt
31 0
|
6月前
|
JSON JavaScript 前端开发
vue2_vite.config.js的proxy跨域配置和nginx配置代理有啥区别?
vue2_vite.config.js的proxy跨域配置和nginx配置代理有啥区别?
227 1
|
6月前
|
JavaScript 安全 前端开发
js开发:请解释什么是跨域请求(CORS),以及如何解决跨域问题。
CORS是一种W3C标准,用于解决浏览器同源策略导致的跨域数据访问限制。它通过服务器在HTTP响应头添加标志允许特定源进行跨域请求。简单请求无需预检,而预检请求(OPTIONS)用于询问服务器是否接受非简单请求。服务器端配置响应头如`Access-Control-Allow-Origin`等实现CORS策略,客户端JavaScript则正常发起请求。若配置不当,浏览器将阻止跨域访问,保障安全。
87 2
|
6月前
|
JavaScript 前端开发 安全
JavaScript中跨域资源共享(CORS):原理和解决方案
【4月更文挑战第22天】本文介绍了JavaScript中跨域资源共享(CORS)的原理和解决方案。CORS借助HTTP头部字段允许跨域请求,核心是Access-Control-Allow-Origin响应头。解决方案包括:服务器端设置响应头(如使用Express.js的cors中间件)、使用代理服务器或JSONP。现代Web开发推荐使用CORS,因为它更安全、灵活,而JSONP已逐渐被淘汰。理解并正确实施CORS能提升Web应用性能和安全性。
|
6月前
|
前端开发 JavaScript 安全
JavaScript高级主题:什么是跨域资源共享(CORS)?
JavaScript高级主题:什么是跨域资源共享(CORS)?
70 0