批改状态:合格
老师批语:写得不错, 已经可以举一反三的
CORS : 跨域资源共享
CSRF : 跨站请求伪造
用户在访问A网站, 此时用户在A网站的信息记录在Cookie中, 假设A网站没有对Cookie做同源策略限制, 此时如果有B网站的链接嵌入到A网站中, 用户点开了该链接后, 跳转到B网站, 假设B网站是不怀好意的网站, 那么B网站的所有者就能获取到A网站的Cookie, 然后使用Cookie以该用户的身份去访问A网站.
产生跨站伪造的原因就是网站没有遵循同源策略
多个页面的协议, 域名, 端口完全相同, 则认为他们遵循了同源策略.
协议: 要么是http, 要么是https等.
域名: 多个页面的域名要完全相同. www.php.cn 和 www.php.net 是不同的!
端口: 要么是80, 要么是443, 或者都是别的, 必须相同.
同源策略是一种安全机制, 浏览器禁止通过脚本发起跨域请求, 如: XMLHttpRequest , Fetch API 等. 但是允许HTML标签属性跨域. 即, 可以用 <a> 标签或 <img> 发送跨域请求或跨域访问.

此时, 若目标网站允许跨域, 则需要在跨域请求的目标请求头指定允许跨域访问自己的站点: header('Access-Control-Allow-Origin: http://php11.edu'). 记得一定要指定协议
header('Access-Control-Allow-Origin: *')
<script src="把需要跨域的脚本URL写到这里发起一个跨域请求"></script>
浏览器允许通过标签属性跨域
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>通过HTML标签属性跨域</title></head><body><img src="https://img.php.cn/upload/image/234/213/408/1590257532837910.png" alt="球员列表" style="width: 400px;"><br><a href="https://www.baidu.com">访问百度</a><br><button type="button">发送跨域请求</button></body></html>

php.edu站点的文件php.edu/0522/test1.php中设置允许站点php11.edu跨域
<?php// 指定允许http://php11.edu站点跨域访问当前文件header('Access-Control-Allow-origin: http://php11.edu');echo '跨域请求返回的数据';// 刷新缓冲区flush();
php11.edu站点的php11.edu/js/0522/demo1.html使用ajax发起跨域访问请求
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>CORS跨域</title></head><body><button type="button">发送跨域请求</button><script>var btn = document.querySelector('button');btn.addEventListener('click', function() {// 通过ajax发送一个跨域请求var xhr = new XMLHttpRequest();xhr.onreadystatechange = function() {if(xhr.readyState === 4 && xhr.status === 200) {console.log(xhr.responseText);}}xhr.open('GET', 'http://php.edu/0522/test1.php', true);xhr.send(null);});</script></body></html>
成功获取到数据

php.edu站点中负责获取请求,并执行查询,调用回调函数.
<?php// 这里返回json数据, 而json只支持utf8编码header('content-type: text/html;charset=utf-8');// 模拟根据id值获取数据, 并调用回调函数处理数据// 获取请求参数(jsonp指定一个回调函数名)$callback = $_GET['jsonp'];$id = $_GET['id'];// 返回的处理结果数组$res = ['status' => '1','message' => '查询成功',];// 判断id值是否有效if(!filter_var($id, FILTER_VALIDATE_INT, ['option' => ['min_range' => 1]])) {$res['status'] = '0';$res['message'] = 'ID值无效';}// 连接数据库$pdo = new PDO('mysql:host=localhost;dbname=phpedu;charset=utf8;port=3306', 'root', 'root');// 查询$stmt = $pdo->query("SELECT * FROM `player` WHERE `id` = {$id}");// 判断是否查到值if(!$stmt || $stmt->rowCount < 1) {// 没查到的处理$res['status'] = '0';$res['message'] = 'ID值无效';} else {// 查到数据$res['data'] = $stmt->fetch(PDO::FETCH_ASSOC);}// 打印回调echo $callback . '(' . json_encode(json_encode($res)) . ')';
php11.edu中通过JSONP发送跨域请求
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>通过JSONP跨域</title></head><body><button>发送跨域请求</button><script>/* 1. 被当做参数值传给跨域的目标站点, 目标站点echo "调用该函数的字符串",相当于在当前站点执行该函数调用 */function handle(jsonData) {// console.log(jsonData);// json=>js对象var res = JSON.parse(jsonData);// 约定状态值为0表示查询结果异常if(res.status === '0') {alert(res.message ?? '查询失败');return;}// 渲染数据var ul = document.createElement('ul');ul.innerHTML += "<ul>姓名: " + res.data.name + "</ul>";ul.innerHTML += "<ul>球队: " + res.data.team + "</ul>";ul.innerHTML += "<ul>身高: " + res.data.height + "</ul>";ul.innerHTML += "<ul>体重: " + res.data.weight + "</ul>";ul.innerHTML += "<ul>位置: " + res.data.position + "</ul>";document.body.appendChild(ul);}</script><script>/* 2. 给按钮增加点击事件, 生成一个跨域请求的script标签 */var btn = document.querySelector('button');btn.addEventListener('click', function () {// 生成一对<script>标签var script = document.createElement("script");// 为script标签的src属性赋予一个跨域请求的url, 并带上handle函数作为回调script.src = "http://php.edu/0522/test2.php?jsonp=handle&id=1";// 把生成的标签加到head标签中document.head.appendChild(script);// 相当于在head标签中生成了下面的标签, 然后就能自动发起跨域请求了// <-script src="http://php.edu/0522/test2.php?jsonp=handle&id=1"><-/script>}, false);</script></body></html>
执行结果:


跨域访问涉及到网站安全, 必须要注意. 成功跨域访问, 一种是访问的目标站点指定了当前站点允许跨域访问(CORS); 另一种是曲线救国, 使用HTML标签的属性发起.
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号