最近在做Freewind-Helper
,就是给Feewind
主题提供一些更多的功能扩展,也打算开发一些功能性API
供大家调用,在开发过程中就突然想到大家可能很多时候是在前端发Ajax
调API,显然,此时过来的请求是跨域请求,然后自已在网上查了些资料给大家分享一下
跨域
首先,大家要知道跨域是怎么产生的?
同源策略
跨域是因为浏览器的同源策略(浏览器上为安全性考虑实施的非常重要的安全策略)所导致
何为同源?我们来看看一个URL的组成协议:\\域名\路径:端口?参数名=参数值&参数名=参数值&...
其中当协议、域名、端口
都相同时才算同源
- 比如
https://www.kevinlu98.cn
与http://www.kevinlu98.cn
这两个URL,它两协议不同,所以不同源 - 比如
https://www.kevinlu98.cn:80
与https://www.kevinlu98.cn:8080
这两个URL,它两的端口不同,很明显不同源 - 比如
https://www.kevinlu98.cn/aaa/bbb/ccc?name=lengwen&age=22
与https://www.kevinlu98.cn
这两个URL,它两只有路径与参数不一样,所以同源
而浏览器的同源策略并不非是限制了发起跨域请求,而是在发起跨域请示时增加一次HTTP请求,称之为预检请求,此次请示使用OPTIONS方法发送到服务器,以获知服务器是否允许该实际请求
解决方案
跨域的解决有不少,大家也可以看出我在谈跨域产生的时候一直在说浏览器的同源策略,也就是说跨域请求只会在浏览器中产生
拿这点来看的话我们似乎有了点解决思路
- 可以用像
NGINX
这样的服务器去做反向代理 - 对于
webpack
这种项目其本身就是运行于nodejs
的,而nodejs
本身就不是浏览器,所以可以直接用nodejs
做一层代理 - 还有其它好多,只要这个跨域请示不是由浏览器发出的,都可以从根本解决跨域问题
- ......
这样是可以解决,但是很明显不可以解决我提出来的问题,我是想给大家去提供API接口让大家去调用,然后总不可能让调用者去解决跨域问题吧
别忘了上面还提到过浏览器不限制跨域请求的发送,所以我们可以在服务端程序里去配合浏览器事先发起的预检请求来完成跨域,在服务端接收到请示时判断是否为OPTIONS
方法,如果是的话返回成功状态码表明允许发起跨域请示,然后在正式请示时在response
的header
中加上允许跨域的信息来防止被浏览器拦截返回
TP5.0解决方案
在项目的application/common
目录下创建behavior
文件夹,在behavior
中创建文件CronRun.php
,写入如下代码
<?php
/**
* @file: CronRun.php
* @Author: lengwen
* @Date: 2021/4/15 8:20 下午
* @Mail: kevinlu98@qq.com
* @description:
*
*/
namespace app\common\behavior;
class CronRun
{
public function run(&$dispatch)
{
header("Access-Control-Allow-Origin:*");
$host_name = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : "*";
$headers = [
"Access-Control-Allow-Origin" => $host_name,
"Access-Control-Allow-Credentials" => 'true',
"Access-Control-Allow-Headers" => "x-token,x-uid,x-token-check,x-requested-with,content-type,Host"
];
if ($dispatch instanceof Response) {
$dispatch->header($headers);
} else if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
//如果是OPTIONS说明是浏览器的预检请求
$dispatch['type'] = 'response';
$response = new Response('', 200, $headers);
$dispatch['response'] = $response;
}
}
}
然后在application/tags.php
里进行行为扩展
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 应用行为扩展定义文件
return [
// 应用初始化
'app_init' => [],
// 应用开始
'app_begin' => [
'app\\common\\behavior\\CronRun'
],
// 模块初始化
'module_init' => [],
// 操作开始执行
'action_begin' => [],
// 视图内容过滤
'view_filter' => [],
// 日志写入
'log_write' => [],
// 应用结束
'app_end' => [
'app\\common\\behavior\\CronRun'
],
];
跨域请示发送成功
看看
多谢大佬分享
强强强
感谢作者!
感谢!