天天看點

thinkphp5 關于跨域的一些坑,附上解決辦法

最近在用uniapp做一個h5的項目(與背景不是同域),在開發的時候發現了一個跨域的問題,一般跨域的問題就是背景配置的問題了~

一般百度找到的方法,就是在入口檔案index.php中添加以下代碼:

header( "Access-Control-Allow-Origin : *" );
header( "Access-Control-Allow-Methods : POST,GET,OPTIONS" );
      

  有的時候,這樣也行,一開始我也是這麼弄的,正常請求了

随便弄了一個路由測試的,沒有問題,但是當放在uniapp的request請求的時候就報錯了,因為請求head中添加了自定義參數token(身份驗證,這個就不多說了)

經過測試發現,隻要不在head中添加自定義參數就沒問題,于是接着找資料,發現還要添加一行:

header( "Access-Control-Allow-Headers : Token,Accept,Accept-Encoding,Accept-Language,Connection,Content-Length,Content-Type,Host,Origin,Referer,User-Agent,X-DevTools-Emulate-Network-Conditions-Client-Id" );
      

  意思就是将所有用到的head參數都寫進去

---------------分隔線------------

本來到這就結束了,但實際并不是這樣。。。。

在找資料的時候,發現一種使用tp5的鈎子的方法,感覺不錯,于是删除了上面添加的代碼,改成下面這樣:

1、在application\common 下建立behavior目錄,在添加添加CronRun.php檔案,内容如下:

<?php

namespace app\common\behavior;

use think\Exception;
use think\Response;

class CronRun
{
    public function run(&$dispatch){
        $host_name = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : "*";
        $headers = [
            "Access-Control-Allow-Origin" => $host_name,
            "Access-Control-Allow-Credentials" => 'true',
            "Access-Control-Allow-Methods" => 'POST,GET,OPTIONS',
            "Access-Control-Allow-Headers" => "Token,Accept,Accept-Encoding,Accept-Language,Connection,Content-Length,Content-Type,Host,Origin,Referer,User-Agent,X-DevTools-Emulate-Network-Conditions-Client-Id"
        ];
        if($dispatch instanceof Response) {
            $dispatch->header($headers);
        } else if($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
            $dispatch['type'] = 'response';
            $response = new Response('', 200, $headers);
            $dispatch['response'] = $response;
        }
    }
}
      

2、在application\tags.php 檔案中修改兩處:

<?php

// 應用行為擴充定義檔案
return [
    // 應用初始化
    'app_init'     => [],
    // 應用開始
    'app_begin'    => [
        'app\\common\\behavior\\CronRun'
    ],
    // 子產品初始化
    'module_init'  => [],
    // 操作開始執行
    'action_begin' => [],
    // 視圖内容過濾
    'view_filter'  => [],
    // 日志寫入
    'log_write'    => [],
    // 應用結束
    'app_end'      => [
        'app\\common\\behavior\\CronRun'
    ],
];
      

3、沒有3了,這樣就可以了,好爽,而且入口檔案也沒有動,感覺還是不錯的。

然而,此時坑來了(當然,與上面的代碼沒有關系)

如果使用了tp5的路由,因為這個項目專門的接口項目,是以配置了config.php檔案,啟用了強制路由,然後為了保證系統的安全,在配置路由的時候沒有使用Route::rule,而是根據接口使用的Route::get或Route::post

這時候我發現一個問題,h5請求接口的時候又跨域了,恩。。。。。鬧心,經過排查發現,就是1、開了強制路由,2、定義路由的時候使用的Route::get,直接就寫死了接口所允許的請求類型(Route::post定義的使用get請求就不行),而跨域會先發一個Option請求,系統正常響應後再發起正常請求,而我用了強制路由,是以一開始的Option請求就沒有正常響應,是以。。。。

總結:

1、要麼不使用強制路由

2、要麼使用Route::rule或在第三個參數裡面配置GET與OPTION

3、别忘了配合上面的代碼一起使用~