>  기사  >  웹 프론트엔드  >  Ajax 도메인 간 문제에 대한 자세한 그래픽 설명(코드 포함)

Ajax 도메인 간 문제에 대한 자세한 그래픽 설명(코드 포함)

php中世界最好的语言
php中世界最好的语言원래의
2018-03-31 15:04:101289검색

이번에는 ajax 크로스 도메인 문제에 대한 자세한 그래픽 설명(코드 포함)을 가져왔습니다. ajax 크로스 도메인 문제에 대한 주의사항은 무엇인가요?

교차 도메인

동일 출처 정책 제한

동일 출처 정책은 한 도메인에 로드된 스크립트가 다른 도메인의 문서 속성을 가져오거나 조작하는 것을 방지합니다. 즉, 요청한 URL의 도메인은 현재 웹페이지의 도메인과 동일해야 합니다. 이는 브라우저가 서로 다른 소스의 콘텐츠를 격리하여 소스 간 작업을 방지한다는 의미입니다.

Solution

일반적으로 두 가지 일반적인 방법이 있습니다. 하나는 서버 측에서, 다른 하나는 클라이언트 관점에서 발생합니다. 둘 다 장단점이 있으며 어떤 방법을 사용할지는 구체적인 분석이 필요합니다.

  1. 서버는 응답 헤더를 설정합니다

  2. 서버 프록시

  3. 클라이언트는 스크립트 콜백 메커니즘을 사용합니다.

방법 1

Access-Control-Allow-Origin 키워드는 서버 측에 설정된 경우에만 적용됩니다. 즉,
client

xmlhttprequest.setHeaderREquest('xx','xx');
에서 사용해도 아무런 효과가 없습니다.

일반 ajax 요청

Ajax 비교차 도메인 요청의 사례 구현을 시뮬레이션해 보겠습니다.

test1.html

nbsp;html>


 <meta>
 <title>ajax 测试</title>


<input>
<p></p>
<script>
 var xhr = new XMLHttpRequest();
 var url = &#39;http://localhost/learn/ajax/test1.php&#39;;
 function crossDomainRequest() {
  document.getElementById(&#39;content&#39;).innerHTML = "<font color=&#39;red&#39;>loading...";
  // 延迟执行
  setTimeout(function () {
   if (xhr) {
    xhr.open(&#39;GEt&#39;, url, true);
    xhr.onreadystatechange = handle_response;
    xhr.send(null);
   } else {
    document.getElementById(&#39;content&#39;).innerText = "不能创建XMLHttpRequest对象";
   }
  }, 3000);
 }
 function handle_response() {
  var container = document.getElementById(&#39;content&#39;);
  if (xhr.readyState == 4) {
   if (xhr.status == 200 || xhr.status == 304) {
    container.innerHTML = xhr.responseText;
   } else {
    container.innerText = &#39;不能跨域请求&#39;;
   }
  }
 }
</script>

같은 디렉토리에 있는 test1.PHP의 내용은 다음과 같습니다.

<?php echo "It Works.";
?>

Ajax 도메인 간 문제에 대한 자세한 그래픽 설명(코드 포함)

Cross-domain request

지금은 HTML 파일과 php 파일이 모두 아래에 있습니다 Apache 컨테이너이므로 도메인 간 요청이 없습니다. 도메인의 경우 이제 HTML 파일을 데스크탑에 놓고 PHP 데이터를 다시 요청하여 이러한 "도메인 간 요청"을 생성합니다.

브라우저의 주소 표시줄 정보에 주의하세요

다시 방문하시면 아래와 같은 오류 메시지를 보실 수 있습니다.

Ajax 도메인 간 문제에 대한 자세한 그래픽 설명(코드 포함)

이 경우 일반적인 작업은 Access-Control-Allow-Origin을 설정하는 것입니다.

형식: Access-Control-Allow-Origin: domain.com/xx/yy.*

클라이언트의 도메인 이름이나 요청의 고정 경로를 알고 있는 경우 추가 보장을 위해 와일드카드를 사용하지 않는 것이 가장 좋습니다. 보안. 확실하지 않은 경우 * 와일드카드 문자를 사용하세요.

백엔드 개발 언어가 PHP인 경우 파일 시작 부분에 이렇게 설정하면 됩니다.

header("Access-Control-Allow-Origin: *");
ASX 페이지인 경우 다음과 같이 설정합니다(Java도 비슷합니다).

Response.AddHeader("Access-Control-Allow-Origin", "*");
여기서 시간, 지금 바로 그 길을 방문해보세요.

Ajax 도메인 간 문제에 대한 자세한 그래픽 설명(코드 포함)

Server프록시 모드

이 방법은 더 일반적으로 사용되고 널리 채택되는 방법으로 간주되어야 합니다. 에이전트라고 하기엔 너무 문자 그대로의 표현인데, 사실은 그냥 메신저일 뿐입니다. 간단한 예를 들어보겠습니다.

샤오밍은 3학년 샤오홍이라는 여자아이를 좋아하지만 너무 부끄러워서 QQ와 위챗 아이디를 물어보지 못합니다. 그러다가 같은 반 여학생인 Xiaolan에게 물었습니다. 와서 그것을 얻을 수 있도록 스스로 도와주세요. 따라서 Xiaolan은 에이전트와 동일합니다. Xiao Ming이 직접 얻을 수 없는 Xiao Hong의 연락처 정보를 얻을 수 있도록 도와주세요.

이 문제를 설명하기 위해 예를 들어 보겠습니다.

직접 도메인 간 요청

지금 바로 URL을 수정하고 Ajax가 다른 웹사이트에서 직접 데이터를 요청하도록 하세요.

nbsp;html>


 <meta>
 <title>ajax 测试</title>


<input>
<p></p>
<script>
 var xhr = new XMLHttpRequest();
// var url = &#39;http://localhost/learn/ajax/test1.php&#39;;
  var url = &#39;http://api.qingyunke.com/api.php?key=free&appid=0&msg=%E5%93%92%E5%93%92&#39;;
 function crossDomainRequest() {
  document.getElementById(&#39;content&#39;).innerHTML = "<font color=&#39;red&#39;>loading...";
  // 延迟执行
  setTimeout(function () {
   if (xhr) {
    xhr.open(&#39;GEt&#39;, url, true);
    xhr.onreadystatechange = handle_response;
    xhr.send(null);
   } else {
    document.getElementById(&#39;content&#39;).innerText = "不能创建XMLHttpRequest对象";
   }
  }, 3000);
 }
 function handle_response() {
  var container = document.getElementById(&#39;content&#39;);
  if (xhr.readyState == 4) {
   if (xhr.status == 200 || xhr.status == 304) {
    container.innerHTML = xhr.responseText;
   } else {
    container.innerText = &#39;不能跨域请求&#39;;
   }
  }
 }
</script>

결과는 다음과 같습니다:

Ajax 도메인 간 문제에 대한 자세한 그래픽 설명(코드 포함)

프록시 모드 활성화

지금 HTML 페이지의 경우 여전히 자체 인터페이스를 사용합니다.

url = 'http://localhost/learn/ajax/test1.php';
세부 사항은 다음과 같습니다.

nbsp;html>


 <meta>
 <title>ajax 测试</title>


<input>
<p></p>
<script>
 var xhr = new XMLHttpRequest();
 var url = &#39;http://localhost/learn/ajax/test1.php&#39;;
//  var url = &#39;http://api.qingyunke.com/api.php?key=free&appid=0&msg=%E5%93%92%E5%93%92&#39;;
 function crossDomainRequest() {
  document.getElementById(&#39;content&#39;).innerHTML = "<font color=&#39;red&#39;>loading...";
  // 延迟执行
  setTimeout(function () {
   if (xhr) {
    xhr.open(&#39;GEt&#39;, url, true);
    xhr.onreadystatechange = handle_response;
    xhr.send(null);
   } else {
    document.getElementById(&#39;content&#39;).innerText = "不能创建XMLHttpRequest对象";
   }
  }, 3000);
 }
 function handle_response() {
  var container = document.getElementById(&#39;content&#39;);
  if (xhr.readyState == 4) {
   if (xhr.status == 200 || xhr.status == 304) {
    container.innerHTML = xhr.responseText;
   } else {
    container.innerText = &#39;不能跨域请求&#39;;
   }
  }
 }
</script>

然后对应的test1.php应该帮助我们实现数据请求这个过程,把“小红的联系方式”要到手,并返回给“小明”。

<?php $url = &#39;http://api.qingyunke.com/api.php?key=free&appid=0&msg=hello%20world.&#39;;
$result = file_get_contents($url);
echo $result;
?>

下面看下代码执行的结果。

Ajax 도메인 간 문제에 대한 자세한 그래픽 설명(코드 포함)

jsonp方式

JSONP(JSON with Padding) 灵感其实源于在HTML页面中script标签内容的加载,对于script的src属性对应的内容,浏览器总是会对其进行加载。于是:

克服该限制更理想方法是在 Web 页面中插入动态脚本元素,该页面源指向其他域中的服务 URL 并且在自身脚本中获取数据。脚本加载时它开始执行。该方法是可行的,因为同源策略不阻止动态脚本插入,并且将脚本看作是从提供 Web 页面的域上加载的。但如果该脚本尝试从另一个域上加载文档,就不会成功。

实现的思路就是:

在服务器端组装出客户端预置好的json数据,通过回调的方式传回给客户端。

原生实现

nbsp;html>


 <meta>
 <title>ajax 测试</title>
 <script></script>


<input>
<input>
<p></p>
<script>
function jsonpcallback(result) {
 for(var i in result) {
  alert(i+":"+result[i]);
 }
 }
 var JSONP = document.createElement("script");
 JSONP.type=&#39;text/javascript&#39;;
 JSONP.src=&#39;http://localhost/learn/ajax/test1.php?callback=jsonpcallback&#39;;
 document.getElementsByTagName(&#39;head&#39;)[0].appendChild(JSONP);
</script>

服务器端test1.php内容如下:

<?php $arr = [1,2,3,4,5,6];
$result = json_encode($arr);
echo "jsonpcallback(".$result.")";
?>

需要注意的是最后组装的返回值内容。

来看下最终的代码执行效果。

Ajax 도메인 간 문제에 대한 자세한 그래픽 설명(코드 포함)

JQuery方式实现

采用原生的JavaScript需要处理的事情还是蛮多的,下面为了简化操作,决定采用jQuery来代替一下。

nbsp;html>


 <meta>
 <title>ajax 测试</title>
 <script></script>


<input>
<input>
<p></p>
<script>
 function later_action(msg) {
  var element = $("<p><font color=&#39;green&#39;>"+msg+"<br />");
  $("#content").append(element);
 }
 $("#btn").click(function(){
  // alert($("#talk").val());
  $.ajax({
  url: &#39;http://localhost/learn/ajax/test1.php&#39;,
  method: &#39;post&#39;,
  dataType: &#39;jsonp&#39;,
  data: {"talk": $("#talk").val()},
  jsonp: &#39;callback&#39;,
  success: function(callback){
   console.log(callback.content);
   later_action(callback.content);
  },
  error: function(err){
   console.log(JSON.stringify(err));
  },
 });
 });
</script>

相应的,test1.php为了配合客户端聊天的需求,也稍微做了点改变。

<?php $requestparam = isset($_GET[&#39;callback&#39;])?$_GET[&#39;callback&#39;]:&#39;callback&#39;;
// 青云志聊天机器人接口: http://api.qingyunke.com/api.php?key=free&appid=0&msg=hello
// 接收来自客户端的请求内容
$talk = $_REQUEST[&#39;talk&#39;];
$result = file_get_contents("http://api.qingyunke.com/api.php?key=free&appid=0&msg=$talk");
// 拼接一些字符串
echo $requestparam . "($result)";
?>

最后来查看一下跨域的效果吧。

JSONP 跨域实现聊天应用

总结

至此,关于简单的ajax跨域问题,就算是解决的差不多了。对我个人而言,对于这三种方式有一点点自己的看法。

  1. 服务器设置Access-Control-Allow-Origin的方式适合信用度高的小型应用或者个人应用。

  2. 代理模式则比较适合大型应用的处理。但是需要一个统一的规范,这样管理和维护起来都会比较方便。

  3. JSONP方式感觉还是比较鸡肋的(有可能是我经验还不足,没认识到这个方式的优点吧(⊙﹏⊙)b)。自己玩玩知道有这么个东西好了。维护起来实在是优点麻烦。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

如何实现AJAX的分页效果

使用Ajax时Json-lib如何处理

위 내용은 Ajax 도메인 간 문제에 대한 자세한 그래픽 설명(코드 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.