专栏首页大龄码农ajax跨域问题

ajax跨域问题

什么事ajax跨域问题

跨域问题来自于浏览器同源策略的限制,包括DOM同源限制和ajax同源限制,本文探讨的是ajax跨域。ajax跨域指的是一个页面的ajax只能请求和当前页面同源的数据,如果发现请求到的数据不符合要求,浏览器就会阻止返回的数据。所谓同源,指的是协议、域名、端口号都必须完全相同(同一ip的不同域名也是跨域)。同源策略的主要目的是防止csrf攻击,它可以有效地避免由于恶意攻击带来的危险,浏览器器同源策略使得网络访问更加安全。

但是,实际开发与生产中,常常获取使用来自其他站点的资源,这时候就需要发起跨域请求,这时候就需要使用特殊的方法来处理,使得我们能够获得想要的数据。

由此可知,跨域仅限于浏览器中,是由于浏览器对不同源数据的拦截产生的,跨域有时候是不可避免的,我们需要采取措施实现跨域请求。

1.浏览器 需用户配置

但意义不大,不可能配置每个客户端的浏览器。

2.XHR-->JSONP

$.ajax({
	url:"http://localhost:8080//test//get1",
	dataType:"jsonp",
	success:function(data){
	    console.log(data);
	}
});

当ajax异步请求增加dataTpe:“jsonp”参数后,发现浏览器控制台没有报错,成功执行了,但通过对比后发现

1.发出去的请求类型在浏览器可以看到是script类型的,浏览器是不会校验的。普通的ajax请求是xhr类型的。

2.返回的类型不同:普通的ajax请求content-type是json,而jsonp的请求content-type是js脚本。

JSONP解决方案, 有很多弊端, 无法满足现在的开发要求,所以JSONP用的越来越少了,所以重点放在第三点。

3.跨域

3.1 被调用方解决

被调用方支持跨域解决思路:基于http协议关于跨域方面的要求而做的修改,从a域名调用b域名时,在b域名返回的信息里加些字段,告诉浏览器b允许a调用。浏览器通过校验就不会报跨域安全问题。

简单请求:先执行后判断

非简单请求:先发出一个预检命令,然后在发出请求。先判断后执行。

3.1.1Filter解决方案

添加一个Class 实现 javax.servlet.Filter

 @Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {


		HttpServletResponse res = (HttpServletResponse)response;
		HttpServletRequest req = (HttpServletRequest)request;
		String origin = req.getHeader("Origin");


		if( !org.springframework.util.StringUtils.isEmpty(origin) ){
			//带cookie的时候 Origin必须是全匹配 , 不能使用*
			res.addHeader("Access-Control-Allow-Origin", origin);
		}
		String header = req.getHeader("Access-Control-Request-Headers");


		//支持所有自定义头
		if( !org.springframework.util.StringUtils.isEmpty(header)){
			res.addHeader("Access-Control-Request-Headers",header);
		}
		res.addHeader("Access-Control-Allow-Methods", "*");
		//options预检命令
		res.addHeader("Access-Control-Allow-Headers", "Content-Type");
		//options预检缓存
		res.addHeader("Access-Control-Max-Age", "3600");
		//enable cookie
		res.addHeader("Access-Control-Allow-Credentials", "true");
		
		chain.doFilter(request, response);
	}

3.1.2 nginx解决方案

首先,先修改本地的host文件

打开 C:\Windows\System32\drivers\etc 路径,打开目录下的host文件,添加 127.0.0.1 traffic.com,表示被调用方的域名。

然后配置虚拟主机,打开nginx的目录,打开conf文件下的nginx.conf文件,

在最后添加 include vhost/*.conf;

[注:vhosts目录需手动创建]

然后在vhost文件夹下添加配置文件 xxx.conf ,并编辑添加内容为

server{

	#监听80端口
	listen 80;
	#域名
	server_name traffic.com;
	
	location /{
		#所有的请求转到 localhost8080
		proxy_pass http://localhost:8080/;
		
		add_header Access-Control-Allow-Methods *;
		#options预检缓存
		add_header Access-Control-Max-Age 3600;
		#enable cookie
		add_header Access-Control-Allow-Credentials true;
		#带cookie的时候 Origin必须是全匹配 , 不能使用*
		add_header Access-Control-Allow-Origin $http_origin;
		#支持所有自定义头
		add_header Access-Control-Allow-Headers $http_access_control_request_headers;
		
		if ($request_method = OPTIONS){
			return 200;
		}
	}
}

然后打开命令提示符,进入到nginx目录下,输入 nginx -t

如图所示即修改配置成功,可以输入 start nginx.exe 启动 nginx

或 输入 nginx -s reload 重新启动nginx

最后通过 ajax异步请求 nginx配置后的域名 http://traffic.com/test/get1

成功。

最后输入 nginx -s stop 停止 nginx

3.1.3 apache解决方案

首先打开 apache目下的 conf/httpd.conf 文件,

以vhost关键字和proxy关键字查找,

把几个模块以及conf文件开放出来

LoadModule vhost_alias_module modules/mod_vhost_alias.so

LoadModule proxy_module modules/mod_proxy.so

LoadModule proxy_http_module modules/mod_proxy_http.so

LoadModule headers_module modules/mod_headers.so

LoadModule rewrite_module modules/mod_rewrite.so

Include conf/extra/httpd-vhosts.conf

然后编辑 conf/extra/httpd-vhosts.conf 文件

添加虚拟主机配置

<VirtualHost *:80>
    #服务器名
    ServerName traffic.com
    #日志
    ErrorLog "logs/traffic.com-error.log"
    CustomLog "logs/traffic.com-access.log" common
    #代理域名
    ProxyPass / http://localhost:8080/
	
    #把请求头的origin值返回到Access-Control-Allow-Origin字段
    Header always set Access-Control-Allow-Origin "expr=%{req:origin}"
	
    #把请求头的Access-Control-Request-Headers值返回到Access-Control-Allow-Headers字段
    Header always set Access-Control-Allow-Header "expr=%{req:Access-Control-Reqest-Headers}"
	
    Header always set Access-Control-Allow-Methods "#"
    Header always set Access-Control-Allow-Credentials "true"
    Header always set Access-Control-Max-Age "3600"
	
    #处理预检命令OPTIONS,直接返回204
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} OPTIONS
    RewriteRule ^(.#)$ "/" [R=204,L]
</VirtualHost>

然后cmd

cd /apache/bin

httpd.exe -k start

启动 apache 测试成功。

3.1.4 spring框架解决方案

在类或者方法上添加注解 @CrossOrigin

3.2 调用方解决

调用方隐藏跨域解决思路:当域名不是自己公司的时,可以用此方法解决。通过一个代理,使得从浏览器发出的请求都是a域名的请求,在代理里面把指定的url转到b域名里面,使得在浏览器上看上去就是同一个域名。

3.2.1 NGINX反向代理配置解决方案

首先,先修改本地的host文件

打开 C:\Windows\System32\drivers\etc 路径,打开目录下的host文件,添加 127.0.0.1 trafficInvoke.com,表示被调用方的域名。

然后在vhost文件夹下添加配置文件 xxx.conf ,并编辑添加内容为

server{

	#监听80端口
	listen 80;
	#域名
	server_name trafficInvoke.com;
	
	location /{
		#所有的请求转到 localhost8081
		proxy_pass http://localhost:8081/;
	}
	
	#反向代理地址 ajaxserver
	location /ajaxserver{
		proxy_pass http://localhost:8080/test/get1;
	}
}

利用反向代理,通过ajax请求到地址 /ajaxserver ,其实就是相对地址 ,欺骗浏览器是同域操作,那就不存在跨域问题了。

3.2.3 APACHE反向代理配置解决方案

<VirtualHost *:80>
    #服务器名
    ServerName trafficInvoke.com
    #日志
    ErrorLog "logs/trafficInvoke.com-error.log"
    CustomLog "logs/trafficInvoke.com-access.log" common
    #反向代理地址 ajaxserver
    ProxyPass /ajaxserverapache http://localhost:8080/test/get1 
    #代理域名
    ProxyPass / http://localhost:8081/
</VirtualHost>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JAVA浮点数看这一篇就够了

    涉及诸如float或者double这两种浮点型数据的处理时,偶尔总会有一些怪怪的现象,不知道大家注意过没,举几个常见的栗子:

    traffic
  • Column count doesn't match value count at row 1

    数据库是mysql 向数据库insert数据的时候,一直显示这个错误,在网上查找了许多相关,大致的问题是: 1:所存储的数据与数据库表的字段类型定义...

    traffic
  • Struts2中action的方法被执行两次

    最近在用struts2遇到一个怪问题,struts2的默认方法老是执行两次,搞了大半天都没有找到,在最后即将放弃时终于找打了,原来是响应的页面有 一个图片标签...

    traffic
  • Python 开发环境管理

    虚拟环境主要合适 virtualenv 和 virtualenvwrapper 来管理,在 Windows 系统上,则使用的是 virtualenvwrappe...

    zucchiniy
  • 在游戏中,爆出神装是真随机还是假随机?

    周末,陪女朋友去电影院看了《复仇者联盟4:终局之战》,作为一个漫威粉三个小时看的是意犹未尽。出来之后,准备和女朋友聊一聊漫威这十年。

    Java3y
  • Django 跨域请求处理

    新人小试
  • SpringBoot项目中加入jsp页面

    根据我们之前搭建好的SpringBoot+SSm的项目的基础上,来增加webapp/WEB-INF的文件,由此来完成jsp页面的跳转.

    Dream城堡
  • How do I know that Association is internally implemented by inner join or outer association

    How do I know that Association is internally implemented by inner join or outer ...

    Jerry Wang
  • linux之查询磁盘情况

    绝命生
  • 【Java面试总结】常用框架之Spring

    Spring 是一种轻量级开发框架,皆在指提高开发人员的开发效率以及系统的可维护性。

    silentcow

扫码关注云+社区

领取腾讯云代金券