通过jsonp和cors实现前端跨域,及需要php的设置

为提高浏览器的安全性,防止xss和csrf攻击,浏览器从一个域名的网页去请求另一个域名的资源时,域名或子域名、端口、协议任一不同,都是跨域。

1.jsonp

由于页面中带有src标签不受同源策略的限制,所以可以通过动态的创建script便签实现跨域情况下的前后端通信。但由于js文件是通过http协议下的get方法加载,因而这种方式应对get请求。

  • php直接输出变量,前端页面直接获取变量
1
2
3
4
5
6
public function indexFunc()
{
$data = json_encode(['j' => 'js']);
echo "var res = {$data}";
exit;
}
1
2
3
4
<script src='http://wx.test.com/index/api/index'></script>
<script>
console.log(res); // {j: "js"}
</script>
  • php输出方法,前端实现方法,传入callback参数
1
2
3
4
5
6
7
8
9
10
11
12
public function indexFunc()
{
if ( array_key_exists('callback', $_GET) ) {
$data = json_encode(['jcb' => 'jscb']);
echo $_GET['callback'] . '(' . $data . ')';
exit;
} else {
$data = json_encode(['j' => 'js']);
echo "var res = {$data}";
exit;
}
}
1
2
3
4
5
6
<script>
function callback(res) {
console.log(res); // {jcb: "jscb"}
}
</script>
<script src='http://wx.test.com/index/api/index?callback=callback'></script>
  • php输出方法,使用jquery的getJSON方法实现
1
2
3
4
5
6
7
8
public function jsonpFunc()
{
$cb = $_GET['callback'];
$data = ['c' => 'callback'];
echo $cb . '(' . \json_encode($data) . ')';
exit;
}
1
2
3
4
5
<script>
$.getJSON('http://wx.test.com/index/api/jsonp?callback=?', function(res) {
console.log(res); // {c: 'callback'}
})
</script>

2.cors

跨源资源共享标准通过新增一系列 HTTP 头,让服务器能声明哪些来源可以通过浏览器访问该服务器上的资源。

  • 不带cookie的get方法,且不限制域名
1
2
3
4
5
6
7
8
9
10
11
public function __construct()
{
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Origin: *");
}
public function corsGetFunc()
{
$data = ['g' => 'get'];
echo \json_encode($data);
exit;
}
1
2
3
$.getJSON('http://wx.test.com/index/api/corsGet', function(res) {
console.log(res); // {g: 'get'}
});
  • 不带cookie的post方法,且不限制域名
1
2
3
4
5
6
7
8
9
10
11
public function __construct()
{
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Origin: *");
}
public function corsPostFunc()
{
$data = ['p' => 'post'];
echo \json_encode($data);
exit;
}
1
2
3
$.post('http://wx.test.com/index/api/corsPost', {}, function(res) {
console.log(res); // {p: 'post'}
}, 'json');
  • 允许带cookie的get,post方法

在cors实现跨域是,当需要前后端需要cookie时,需要前后端分别设置设置header(“Access-Control-Allow-Credentials: true”);withCredentials: true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public function __construct()
{
header("Access-Control-Allow-Credentials: true");
$last_host = $_SERVER['HTTP_REFERER'];
if ($last_host[4] == 's') {
preg_match("/^(https:\/\/)?([^\/]+)/i", $last_host, $matches);
header("Access-Control-Allow-Origin: https://{$matches[2]}");
} else {
preg_match("/^(http:\/\/)?([^\/]+)/i", $last_host, $matches);
header("Access-Control-Allow-Origin: http://{$matches[2]}");
}
}
public function corsGetFunc()
{
setcookie('name_get', 'yole_get', time() + 60 * 60);
$data = ['g' => 'get'];
echo \json_encode($data);
exit;
}
public function corsPostFunc()
{
setcookie('name_post', 'yole_post', time() + 60 * 60);
$data = ['p' => 'post'];
echo \json_encode($data);
exit;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$.ajax({
type: 'get',
url: 'http://wx.test.com/index/api/corsGet',
xhrFields: {
withCredentials: true,
},
corssDomain: true,
data: {},
dataType: 'json',
success: function(res) {
console.log(res);
}
})
$.ajax({
type: 'post',
url: 'http://wx.test.com/index/api/corsPost',
xhrFields: {
withCredentials: true,
},
corssDomain: true,
data: {},
dataType: 'json',
success: function(res) {
console.log(res);
}
})

— end —