精华内容
下载资源
问答
  • ajax跨域问题

    万次阅读 2018-06-07 00:18:44
    什么事ajax跨域问题 跨域问题来自于浏览器同源策略的限制,包括DOM同源限制和ajax同源限制,本文探讨的是ajax跨域。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>

     

     

            

    更多技术干货,请观柱贡眾呺 【程序论】

     

     

    展开全文
  • AJAX跨域问题

    2021-01-22 15:06:08
    AJAX跨域问题 1.什么是AJAX跨域问题        前后端分离开发的模式下,存在前端页面只能请求同一个域下的后端接口,如果不是同一个域,就会产生跨域问题。 2.为什么会发生AJAX...

    AJAX跨域问题

    1.什么是AJAX跨域问题

           前后端分离开发的模式下,存在前端页面只能请求同一个域下的后端接口,如果不是同一个域,就会产生跨域问题。
    在这里插入图片描述

    2.为什么会发生AJAX跨域?

    1.浏览器限制,并而不是服务器后台不允许调用。
    2.跨域:协议,域名(IP),端口,任何一个不一样,浏览器就会认为是跨域
    3.我们发送的是XHR(XMLHttpRequest请求)

    3.解决思路

    1.浏览器限制:我们跨域通过指定参数,让浏览器不作限制,这种方法意义不大,需要每一个浏览器客户端都做限制不现实。
    2.XHR,只要我们发送都请求不是XHR类型的,就算是跨域的,浏览器页不会报跨域安全问题。基于这个思路,我们的解决方案是JSONP。
    3.跨域,1.被调用方修改代码(支持跨域),支持基于http协议关于跨域方面的要求而做的修改。2.调用方修改代码(隐藏跨域),通过一个代理,在浏览器发送出去都是a域名的请求,在代理里面,都转到b域名里面。这样浏览器看上去就算同一个域名,就不会发生跨域。

    4.浏览器禁止检查

    浏览器通过终端打开:
    windows:

    chrome.exe–disable-web-security -user-data-dir=/Users/seeker/webtrash
    

    mac:

    open -n /Applications/Google\ Chrome.app/ --args --disable-web-security  --user-data-dir=/Users/seeker/webtrash
    

    (mac中/Applications/Google Chrome.app是谷歌浏览器的位置,这里需要注意用""表示跳脱字符将特殊字符变成一般字符(如enter,$,空格等))
    (-user-data-dir= /Users/seeker/webtrash 表示浏览器禁止安全检查的临时存放数据目录)

    展开全文
  • Ajax跨域问题

    2016-02-12 13:09:07
    Ajax跨域问题 借助一个jQuery的插件:jquery-jsonpvar url="http://localhost:8080/WorkGroupManagment/open/getGroupById" +"?id=1&callback=?"; $.jsonp({ "url": url, "success": function(data) { $("#...

    借助jQuery的插件:jquery-jsonp

    var url="http://localhost:8080/test/adv/findList/"
        +"?pid=1&callback=?";
    $.jsonp({
      "url": url,
      "success": function(data) {
        // 成功的代码
      },
      "error": function(e, msg) {
        // 失败的代码
      }
    });
    展开全文
  • 解决ajax跨域问题【5种解决方案】

    万次阅读 多人点赞 2018-09-02 21:31:33
    什么是跨域问题? 跨域问题来源于JavaScript的"同源策略",即只有 协议+主机名+...跨域问题是针对JS和ajax的,html本身没有跨域问题。 查看浏览器开发者工具Console报错: Failed to load http://a.a.com:8080/A/...

    什么是跨域问题?

    跨域问题来源于JavaScript的"同源策略",即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。跨域问题是针对JS和ajax的,html本身没有跨域问题。

    查看浏览器开发者工具Console报错:

    Failed to load http://a.a.com:8080/A/FromServlet?userName=123: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://b.b.com:8080' is therefore not allowed access.

    http://www.abc.com/a/b 调用 http://www.abc.com/d/c(非跨域)

    http://www.abc.com/a/b 调用 http://www.def.com/a/b (跨域:域名不一致)

    http://www.abc.com:8080/a/b 调用 http://www.abc.com:8081/d/c (跨域:端口不一致)

    http://www.abc.com/a/b 调用 https://www.abc.com/d/c (跨域:协议不同)

    请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。

     

     

    跨域问题怎么解决?

    1、响应头添加Header允许访问

    2、jsonp 只支持get请求不支持post请求

    3、httpClient内部转发

    4、使用接口网关——nginx、springcloud zuul   (互联网公司常规解决方案)

     

    解决方式1:响应头添加Header允许访问

    跨域资源共享(CORS)Cross-Origin Resource Sharing

    这个跨域访问的解决方案的安全基础是基于"JavaScript无法控制该HTTP头"

    它需要通过目标域返回的HTTP头来授权是否允许跨域访问。

    response.addHeader(‘Access-Control-Allow-Origin:*’);//允许所有来源访问 
    response.addHeader(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式

     

    解决方式2:jsonp 只支持get请求不支持post请求

    用法:①dataType改为jsonp     ②jsonp : "jsonpCallback"————发送到后端实际为http://a.a.com/a/FromServlet?userName=644064&jsonpCallback=jQueryxxx     ③后端获取get请求中的jsonpCallback    ④构造回调结构

    $.ajax({
    			type : "GET",
    			async : false,
    			url : "http://a.a.com/a/FromServlet?userName=644064",
    			dataType : "jsonp",//数据类型为jsonp  
    			jsonp : "jsonpCallback",//服务端用于接收callback调用的function名的参数
    			success : function(data) {
    				alert(data["userName"]);
    			},
    			error : function() {
    				alert('fail');
    			}
    		});
    

     

    //后端
            String jsonpCallback = request.getParameter("jsonpCallback");
    		//构造回调函数格式jsonpCallback(数据)
    		resp.getWriter().println(jsonpCallback+"("+jsonObject.toJSONString()+")");

    JSONP实现原理

    在同源策略下,在某个服务器下的页面是无法获取到该服务器以外的数据的,即一般的ajax是不能进行跨域请求的。但 img、iframe 、script等标签是个例外,这些标签可以通过src属性请求到其他服务器上的数据。利用<script>标签的开放策略,我们可以实现跨域请求数据,当然这需要服务器端的配合。 Jquery中ajax的核心是通过 XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的 js脚本。

      当我们正常地请求一个JSON数据的时候,服务端返回的是一串JSON类型的数据,而我们使用 JSONP模式来请求数据的时候服务端返回的是一段可执行的JavaScript代码。因为jsonp 跨域的原理就是用的动态加载<script>的src ,所以我们只能把参数通过url的方式传递,所以jsonp的 type类型只能是get !

    示例:

    $.ajax({

        url: 'http://192.168.10.46/demo/test.jsp',        //不同的域

        type: 'GET',                                                        // jsonp模式只有GET 是合法的

        data: {

            'action': 'aaron'

        },

        dataType: 'jsonp',                                              // 数据类型

        jsonp: 'jsonpCallback',                                     // 指定回调函数名,与服务器端接收的一致,并回传回来

    })

    其实jquery 内部会转化成

    http://192.168.10.46/demo/test.jsp?jsonpCallback=jQuery202003573935762227615_1402643146875&action=aaron

    然后动态加载

    <script type="text/javascript"src="http://192.168.10.46/demo/test.jsp?jsonpCallback= jQuery202003573935762227615_1402643146875&action=aaron"></script>

    然后后端就会执行jsonpCallback(传递参数 ),把数据通过实参的形式发送出去。

      使用JSONP 模式来请求数据的整个流程:客户端发送一个请求,规定一个可执行的函数名(这里就是 jQuery做了封装的处理,自动帮你生成回调函数并把数据取出来供success属性方法来调用,而不是传递的一个回调句柄),服务器端接受了这个 jsonpCallback函数名,然后把数据通过实参的形式发送出去

     

    (在jquery 源码中, jsonp的实现方式是动态添加<script>标签来调用服务器提供的 js脚本。jquery 会在window对象中加载一个全局的函数,当 <script>代码插入时函数执行,执行完毕后就 <script>会被移除。同时jquery还对非跨域的请求进行了优化,如果这个请求是在同一个域名下那么他就会像正常的 Ajax请求一样工作。)

     

    解决方式3:httpClient内部转发

    实现原理很简单,若想在B站点中通过Ajax访问A站点获取结果,固然有ajax跨域问题,但在B站点中访问B站点获取结果,不存在跨域问题,这种方式实际上是在B站点中ajax请求访问B站点的HttpClient,再通过HttpClient转发请求获取A站点的数据结果。但这种方式产生了两次请求,效率低,但内部请求,抓包工具无法分析,安全。

    $.ajax({
    			type : "GET",
    			async : false,
    			url : "http://b.b.com:8080/B/FromAjaxservlet?userName=644064",
    			dataType : "json",
    			success : function(data) {
    				alert(data["userName"]);
    			},
    			error : function() {
    				alert('fail');
    			}
    		});

     

    @WebServlet("/FromAjaxservlet")
    public class FromAjaxservlet extends HttpServlet{
    	
    	
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		try {
    			//创建默认连接
    			CloseableHttpClient httpClient = HttpClients.createDefault();
    			//创建HttpGet对象,处理get请求,转发到A站点
    			HttpGet httpGet = new HttpGet("http://a.a.com:8080/A/FromServlet?userName="+req.getParameter("userName")); 
                            //执行
    			CloseableHttpResponse response = httpClient.execute(httpGet);
    			int code = response.getStatusLine().getStatusCode();
    			//获取状态
    			System.out.println("http请求结果为:"+code);
    			if(code == 200){
                                    //获取A站点返回的结果
    				String result = EntityUtils.toString(response.getEntity());
    				System.out.println(result);
                                    //把结果返回给B站点
    				resp.getWriter().print(result);
    			}
    			response.close();
    			httpClient.close();
    		} catch (Exception e) {
    		}
    	}
    }

     

    解决方式4:使用nginx搭建企业级接口网关方式

    www.a.a.com不能直接请求www.b.b.com的内容,可以通过nginx,根据同域名,但项目名不同进行区分。什么意思呢?这么说可能有点抽象。假设我们公司域名叫www.nginxtest.com

    当我们需要访问www.a.a.com通过www.nginxtest.com/A访问,并通过nginx转发到www.a.a.com

    当我们需要访问www.b.b.com通过www.nginxtest.com/B访问,并通过nginx转发到www.a.a.com

    我们访问公司的域名时,是"同源"的,只是项目名不同,此时项目名的作用只是为了区分,方便转发。如果你还不理解的话,先看看我是怎么进行配置的:

    server {
            listen       80;
            server_name  www.nginxtest.com;
            location /A {
    		    proxy_pass  http://a.a.com:81;
    			index  index.html index.htm;
            }
    		location /B {
    		    proxy_pass  http://b.b.com:81;
    			index  index.html index.htm;
            }
        }
    

    我们访问以www.nginxtest.com开头且端口为80的网址,nginx将会进行拦截匹配,若项目名为A,则分发到a.a.com:81。实际上就是通过"同源"的域名,不同的项目名进行区分,通过nginx拦截匹配,转发到对应的网址。整个过程,两次请求,第一次请求nginx服务器,第二次nginx服务器通过拦截匹配分发到对应的网址。

     

    解决方式5:使用Spring Cloud zuul接口网关

    我比较懒...

    展开全文
  • Ajax 跨域问题

    2018-04-24 14:17:59
    https://segmentfault.com/a/1190000012469713https://www.cnblogs.com/lxwphp/p/8080188.html 题纲 关于跨域,有N种类型,本文只专注于ajax请求跨域(,ajax跨域只是属于浏览器”同源策略”中的一部分,其它的还有...
  • PHP Ajax 跨域问题解决方案PHP Ajax 跨域问题解决方案通过设置`Access-Control-Allow-Origin`来实现跨域。#### 例如:客户端的域名是`client.web3.xin`,而请求的域名是`server.web3.xin`。如果直接使用ajax访问,会...
  • ajax 跨域问题

    2018-09-17 09:42:32
    为什么会出现跨域 跨域问题来源于JavaScript的同源...跨域问题是针对JS和ajax的,html本身没有跨域问题,比如a标签、script标签、甚至form标签(可以直接跨域发送数据并接收数据)等 ![这里写图片描述](https://i...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,194
精华内容 3,677
关键字:

ajax跨域问题