如標題:我想在ajax的header頭增長自定義Token進行跨域api認證並調用,api使用laravel5編寫,如何實現?javascript
首先,瞭解下CORS簡單請求和複雜請求。php
-- CORS簡單請求 -- html
連接:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS前端
一、ajax跨域,使用CORS方式 -- (ajax跨域會自動提交origin字段,用戶不可僞造)java
二、HTML的js:ios
</body> <script type="text/javascript"> $(function(){ $(document).on("click", ".btn-all2", function(){ $.ajax({ url:"http://t-local.*****.com/wechat/auth/up?call_back=http%3A%2F%2Ftest.*****.com%2Findex.php%3Fg%3DWeixin%26m%3DWeixin%26a%3Dindex", dataType:"json", type:"get", //origin字段不容許自定義僞造;跨域請求瀏覽器自動帶上origin // 容許攜帶cookie憑證 xhrFields: { withCredentials: true }, // 容許跨域 crossDomain: true, success:function(data){ console.log('success'); console.log(JSON.stringify(data)); }, error: function(data){ console.log('error'); console.log(JSON.stringify(data)); } }) }) }) </script> </html>
laravel5後臺ajax請求過濾中間件: -- laravel 5 用來處理【簡單請求】或者【複雜請求的第二次請求】laravel
//跨域XML請求,會自動帶上http_origin字段
public function handle( $request, Closure $next )
{
$origin = isset($_SERVER['HTTP_ORIGIN'])? $_SERVER['HTTP_ORIGIN'] : '';
$allow_origin = Config::get('app.allow_origin');
$allow_origin_dynamic = Config::get('app.allow_origin_dynamic');
$allowOrigin = false;
if ( in_array( $origin, $allow_origin ))
{
$allowOrigin = true;
} else {
foreach ( $allow_origin_dynamic as $item )
{
if ( strpos( $origin, $item ) !== false )
{
$allowOrigin = true;
break;
}
}
}
if ( $allowOrigin )
{
header('Access-Control-Allow-Origin: '.$origin);
header('Access-Control-Allow-Methods:POST,GET,OPTIONS,PUT,DELETE');
header('Access-Control-Allow-Headers:x-requested-with,content-type');
header('Access-Control-Allow-Credentials:true');
}
return $next($request);
}
------ CORS複雜請求 --------ajax
連接:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORSjson
複雜請求 =【預請求 + 簡單請求】;axios
一次XMLHttpRequest會發送兩次請求,一次options、一次自定義的請求
那麼在TP5中,咱們可使用行爲擴展處理ajax|axios 帶自定義頭token的CORS請求,在laravel5中怎樣解決呢?
laravel5 解決方案:
一、域名一:local.domian.com前端發起跨域ajax請求:訪問laravel5的t-local.domian.com域名二
<script type="text/javascript"> $(function(){ $(document).on("click", ".btn-all2", function(){ $.ajax({ url:"http://t-local.****.com/api/wechat/auth/up?call_back=http%3A%2F%2Ftest.****.com%2Findex.php%3Fg%3DWeixin%26m%3DWeixin%26a%3Dindex", dataType:"json", type:"get", //origin字段不容許自定義僞造;跨域請求瀏覽器自動帶上origin //自定義請求頭認證token headers: { 'token' : "2211zxz" }, // 容許攜帶cookie憑證 xhrFields: { withCredentials: true }, // 容許跨域 crossDomain: true, success:function(data){ console.log('success'); console.log(JSON.stringify(data)); }, error: function(data){ console.log('error'); console.log(JSON.stringify(data)); } }) }) }) </script>
二、在laravel的route/api.php路由文件,增長如下路由規則:
/**
* laravel5發送複雜cors請求,相似jwt、自定義請求頭token等,會先發送預請求options
* @param : 預請求options的【Access-Control-Allow-Origin:】絕對不能夠設置成*,不然報錯
* @return : code 200
* date: 2019年10月30日下午2:29:50
* author: xzz
*/
Route::options('/{all}',function () {
//file_put_contents(storage_path('logs/SERVER_Header.txt'), 'array = ' . var_export(request()->header(), true) . PHP_EOL, FILE_APPEND);
//file_put_contents(storage_path('logs/SERVER_Header.txt'), 'string' . var_export(request()->header('ORIGIN'), true) . PHP_EOL, FILE_APPEND);
$origin = request()->header('ORIGIN')??request()->header('HTTP_ORIGIN');
header("Access-Control-Allow-Origin: $origin");
header("Access-Control-Allow-Credentials: true");
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
header('Access-Control-Allow-Headers: Origin, Access-Control-Request-Headers, SERVER_NAME, Access-Control-Allow-Headers, cache-control, token, X-Requested-With, Content-Type, Accept, Connection, User-Agent');
})->where(['all' => '([a-zA-Z0-9-]|/)*']);
三、返回前端F12打開,發現options請求已經過:
四、在建立一個【ajax簡單請求】驗證中間件(若是是簡單請求,上面均可以省略),App\Middleware\AjaxHeader.php,kernel.php註冊在api裏面
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\{Config}; class AjaxHeader { /** * @param $request * @param Closure $next * @return mixed */ public function handle( $request, Closure $next ) { file_put_contents(storage_path('logs/1.txt'), var_export($_SERVER, true) . PHP_EOL, FILE_APPEND); file_put_contents(storage_path('logs/SERVER_HeaderReal.txt'), 'array = ' . var_export(request()->header(), true) . PHP_EOL, FILE_APPEND); file_put_contents(storage_path('logs/SERVER_HeaderReal.txt'), 'string' . var_export(request()->header('ORIGIN'), true) . PHP_EOL, FILE_APPEND); $origin = isset($_SERVER['HTTP_ORIGIN'])? $_SERVER['HTTP_ORIGIN'] : ''; $allow_origin = Config::get('app.allow_origin'); $allow_origin_dynamic = Config::get('app.allow_origin_dynamic'); $allowOrigin = false; if ( in_array( $origin, $allow_origin )) { $allowOrigin = true; } else { foreach ( $allow_origin_dynamic as $item ) { if ( strpos( $origin, $item ) !== false ) { $allowOrigin = true; break; } } } if ( $allowOrigin ) { header('Access-Control-Allow-Origin: '.$origin); header('Access-Control-Allow-Methods:POST,GET,OPTIONS,PUT,DELETE'); header('Access-Control-Allow-Headers:x-requested-with,content-type,token'); header('Access-Control-Allow-Credentials:true'); } return $next($request); /* return $next($request)-> header('Access-Control-Allow-Origin', '*') -> header('Access-Control-Allow-Methods', 'POST,GET,OPTIONS,PUT,DELETE') -> header('Access-Control-Allow-Headers', 'Content-Type,Accept,Authorization,X-Requested-With');*/ } }
五、上面註冊的api中間件綁定到t-local的api/wechat/xxx路由上,從local域名發起訪問t-local域名,發現get請求也成功返回了json數據
返回的json數據:數據正確返回了,至於返回的是什麼,這已經不重要了,不是嗎?!!
六、至此,則完成了laravel5 處理ajax 攜帶自定義header頭Token,併發起的跨域CORS的複雜請求。