为什么发送OPTIONS请求
- 获取服务器支持的HTTP请求方法;
- 用来检查服务器的性能。例如:AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个HTTP OPTIONS请求头,用以判断实际发送的请求是否安全。
如何处理OPTIONS请求
经典解决方法
一般而言,只需要加入以下三行代码即可解决
//指定允许其他域名访问
header(‘Access-Control-Allow-Origin:*‘);
//响应类型
header(‘Access-Control-Allow-Methods:*‘);
//响应头设置
header(‘Access-Control-Allow-Headers:x-requested-with,content-type‘);
但是这个方法在thinkphp框架中使用时,如果有多个控制器,或控制器下的方法比较多,又不能明确确定哪些需要跨域哪些不需要的情况下,逐个方法添加这三行代码,显得非常僵硬。
更优雅的方法
在./application/index/tags.php
中找到app_init,并注册解决跨域的类
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 应用行为扩展定义文件
return [
// 应用初始化
‘app_init‘ => [‘app\index\behavior\CORS‘],
// 应用开始
‘app_begin‘ => [],
// 模块初始化
‘module_init‘ => [],
// 操作开始执行
‘action_begin‘ => [],
// 视图内容过滤
‘view_filter‘ => [],
// 日志写入
‘log_write‘ => [],
// 应用结束
‘app_end‘ => [],
];
在./application/index/behavior/
中新建一个cors.php,将我们要拦截并添加的三行代码放上去
<?php
namespace app\index\behavior;
use think\Response;
class CORS
{
public function appInit(){
header(‘Access-Control-Allow-Origin:*‘);
header(‘Access-Control-Allow-Methods:*‘);
header(‘Access-Control-Allow-Headers:x-requested-with,content-type‘);
}
}
使用postman测试,发现有如下三行headers即为成功。
跨域问题解决的原理
观察上面的三行代码可以发现,只需要在response中加入这三个header就可以了。一般情况下,只要有合适的认证机制(如token)就可以有效防止CSRF攻击,因此可以直接设置一个全局的跨域。