博客列表 >JS - 跨域请求 CORS 与 JSONP

JS - 跨域请求 CORS 与 JSONP

晴天
晴天原创
2020年05月24日 14:29:16726浏览

1.跨域请求

  • CORS:跨域资源共享

  • CSRF:跨站请求伪造

1.1 JS 默认遵循同源策略

  • 多个页面的 协议,域名,端口 完全相同,则认为他们遵循了同源策略
  • 同源策略是一种安全机制
  • 浏览器禁止通过脚本发起跨域请求,如XMLHttpRequest但允许通过html标签属性跨域

php 文件

  1. <?php
  2. echo sha1(1);
  • 如果 php 文件与当前页在同一域名下则允许访问
  1. <button>跨站请求</button>
  2. <h2></h2>
  3. <script>
  4. // 按钮被单击跨站请求;
  5. var btn = document.querySelector("button");
  6. btn.addEventListener(
  7. "click",
  8. function () {
  9. // 创建异步请求
  10. var xhr = new XMLHttpRequest();
  11. // 监听返回值
  12. xhr.onreadystatechange = function () {
  13. if (xhr.readyState === 4 && xhr.status === 200) {
  14. console.log(xhr.responseText);
  15. document.querySelector("h2").innerHTML = xhr.responseText;
  16. }
  17. };
  18. // 初始化请求参数 同一域名
  19. xhr.open("get", "test.php", true);
  20. // 发送请求
  21. xhr.send(null);
  22. },
  23. false
  24. );

  • 如果不在
  1. // 初始化请求参数 不同域名
  2. xhr.open("get", "http://php11.edu/0522/test.php", true);

则会提示你禁止跨域

如果你非要跨域,也不是没有办法在 PHP 文件头部添加代码

  1. <?php
  2. header("Access-Control-Allow-Origin:http://js.edu");
  3. echo sha1(1);

跨域成功

2. JSONP

  • 同源策略禁止通过脚本发起跨域请求, 但是允许通过标签和属性发起一个跨域

  • 也就是 我们可以在<script src = ""></script> src 属性上下功夫,比如在 js 中写好方法,加载 src 时调用该方法并传参

php 部分

  1. <?php
  2. // 获取到id
  3. $id = $_GET['id'];
  4. $users = [
  5. '{"name":"Jerry", "email":"Jerry@qq.com"}',
  6. '{"name":"John", "email":"John@qq.com"}',
  7. '{"name":"Amy", "email":"Amy@qq.com"}',
  8. ];
  9. // 循环输出
  10. switch ($id) {
  11. case '1':
  12. echo "handle(". json_encode($users[0]).")";
  13. break;
  14. case '2':
  15. echo "handle(". json_encode($users[1]).")";
  16. break;
  17. case '3':
  18. echo "handle(". json_encode($users[2]).")";
  19. break;
  20. }

js 部分

  1. <button>JSONP跨站请求</button>
  2. <script>
  3. // 先创建一个方法
  4. function handle(jsonData) {
  5. console.log(jsonData);
  6. // 解析json
  7. var data = JSON.parse(jsonData);
  8. console.log(data);
  9. // 接接口返回值渲染到页面
  10. var ul = document.createElement("ul");
  11. ul.innerHTML += "<li>姓名:" + data.name + "</li>";
  12. ul.innerHTML += "<li>邮箱: " + data.email + "</li>";
  13. // 插入页面中
  14. document.body.appendChild(ul);
  15. }
  16. // 点击按钮发起基于JSONP的跨域请求
  17. var btn = document.querySelector("button");
  18. btn.addEventListener(
  19. "click",
  20. function () {
  21. // 创建一个标签
  22. var script = document.createElement("script");
  23. // 给标签的src赋值
  24. script.src = "http://php11.edu/0522/handle.php?id=1";
  25. // 将标签插入head中
  26. document.head.appendChild(script);
  27. },
  28. false
  29. );
  30. </script>

3. 基于 JSONP 简单做一个查询功能

index.html

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>Document</title>
  7. <link rel="stylesheet" href="style.css" />
  8. </head>
  9. <body>
  10. <h2>查询员工信息</h2>
  11. <form action="" onsubmit="return false">
  12. <div>
  13. <input
  14. type="text"
  15. name="msg"
  16. placeholder="type your message"
  17. required
  18. />
  19. <select name="type">
  20. <option value="id">id</option>
  21. <option value="name">name</option>
  22. <option value="mobile">mobile</option>
  23. <option value="position">position</option>
  24. <option value="age">age</option>
  25. </select>
  26. </div>
  27. <button>查询</button>
  28. </form>
  29. </body>
  30. <script>
  31. // 获取按钮 和 表单
  32. var btn = document.querySelector("button");
  33. var select = document.querySelector("select");
  34. var input = document.querySelector("input");
  35. var head = document.querySelector("head");
  36. var body = document.querySelector("body");
  37. // 按钮被单击
  38. btn.addEventListener(
  39. "click",
  40. function () {
  41. var head_script = document.querySelectorAll("head > script");
  42. // 先检测head中有没有script
  43. if (head_script.length !== 0) {
  44. // 全部删除
  45. for (var i = 0; i < head_script.length; i++) {
  46. head.removeChild(head_script[i]);
  47. }
  48. }
  49. // 判断如果input有值插入script标签
  50. if (input.value !== ""){
  51. var script = document.createElement("script");
  52. script.src =
  53. "handle.php?action=" + select.value + "&value=" + encodeURIComponent(input.value);
  54. document.head.appendChild(script);
  55. }
  56. },
  57. false
  58. );
  59. // 创建函数
  60. function handle(jsonDate) {
  61. // 先检测有没有table 有的话删除
  62. var table = document.querySelectorAll("body > table");
  63. if (table.length !== 0) {
  64. // 全部删除
  65. for (var i = 0; i < table.length; i++) {
  66. body.removeChild(table[i]);
  67. }
  68. }
  69. // 创建table
  70. var table = document.createElement("table");
  71. // 首行
  72. table.innerHTML += "<tr><th>id</th><th>name</th><th>mobile</th><th>position</th><th>age</th></tr>";
  73. // 判断输出
  74. if (jsonDate.message === 0){
  75. // 0 = 没找到
  76. table.innerHTML += "<tr><td colspan='5'>"+jsonDate.value+"</td></tr>"
  77. }else {
  78. // 找到返回多维数组
  79. for (var i = 0; i < jsonDate.value.length; i++) {
  80. table.innerHTML += "<tr>" + "<td>" + jsonDate.value[i]['id'] + "</td>" + "<td>" + jsonDate.value[i]['name'] + "</td>" + "<td>" + jsonDate.value[i]['mobile'] + "</td>" + "<td>" + jsonDate.value[i]['position'] + "</td>" + "<td>" + jsonDate.value[i]['age'] + "</td>" + "</tr>"
  81. }
  82. }
  83. // 插入
  84. document.body.appendChild(table);
  85. }
  86. </script>
  87. </html>

handle.php

  1. <?php
  2. //先判断有没有get
  3. if (empty($_GET)){
  4. die("非法请求");
  5. }
  6. //获取GET值
  7. $action = $_GET['action'];
  8. //value值需要解码
  9. $value = urldecode($_GET['value']);
  10. //创建一个查询函数
  11. function sel($where,$value){
  12. $pdo = new PDO('mysql:host=localhost;dbname=php11.edu','php11.edu','php11.edu');
  13. $stmt = $pdo->prepare("SELECT * FROM `staffs` WHERE `{$where}`='{$value}'");
  14. $stmt->execute();
  15. // 获取多维数组
  16. $value = $stmt->fetchAll(PDO::FETCH_ASSOC);
  17. // 检测返回是否是空数组
  18. if (!empty($value)){
  19. return ["message"=>1,"value"=>$value];
  20. }else{
  21. return ["message"=>0,"value"=>"员工不存在或输入错误"];
  22. }
  23. }
  24. echo "handle(".json_encode(sel($action,$value)).")";

4. 总结

  • 意外发现php json编码后的数组刚好是js的对象字面量 前端不用解码 直接可以用
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议