laravel 5.5 oauth2.0 跨域問題解決方案
一、laravel-Cors
- 安裝
在終端執行安裝命令如下:
composer require barryvdh/laravel-cors
- 添加服務提供商
在Laravel配置文件app.php
的providers
數組中添加如下配置:
Barryvdh\Cors\ServiceProvider::class,
- 發布配置文件
執行在終端執行發布配置文件命令如下:
php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider"
執行後會在laravel目錄下的config目錄中新增cors.php
至此laravel-Cors
安裝完成。
備註
- 什麽是跨域
跨域是指從一個域名的網頁去請求另一個域名的資源。比如從www.baidu.com 頁面去請求 www.google.com 的資源。跨域的嚴格一點的定義是:只要 協議,域名,端口有任何一個的不同,就被當作是跨域
- 為什麽瀏覽器要限制跨域訪問
原因就是安全問題:如果一個網頁可以隨意地訪問另外一個網站的資源,那麽就有可能在客戶完全不知情的情況下出現安全問題。
- 為什麽要跨域
既然有安全問題,那為什麽又要跨域呢? 有時公司內部有多個不同的子域,比如一個是b.a.com ,而應用是放在c.a.com , 這時想從b.a.com去訪問 location.company.com 的資源就屬於跨域。
- 如何解決跨域問題
跨域訪問需要用到兩樣東東,一個是JSON,一種基於文本的傳輸協議;一種是JSONP,一群碼農想出來的跨域解決方案。
- 服務端需要做的
服務端要檢查訪問的請求參數,如果沒有callback,則可以按照之前的流程走;如果帶著callback參數,則需要將返回的結果包裝在callback裏面。
- 客戶端(瀏覽器)需要做的
客戶端可以多種方式可以實現JSONP的調用
- larave-cors做了什麽
CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。
它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
laravel-cors
The
laravel-cors
package allows you to send Cross-Origin Resource Sharing headers with ACL-style per-url configuration.
也就是說,laravel-cors
是在服務端允許了所有帶有跨域資源請求的header,並當成正常請求處理,從服務端解決了跨域資源共享的問題。
關於更多的laravel-cors
使用配置,請移步 larave-cors官方GitHub倉庫
第二種,最方便的,新建一個middleWare,把這個middleware加入到全局中間件,所有的請求,都會經過這個中間件的過濾。
php artisan make:middleware CrossHttp
然後就會在\app\Http\Middleware\CrossHttp.php這個中間件,在handle方法裏面添加如下代碼:
public function handle($request, Closure $next) {
$response = $next($request);
$response->header(‘Access-Control-Allow-Origin‘, ‘*‘);
$response->header(‘Access-Control-Allow-Headers‘, ‘Origin, Content-Type, Cookie, Accept‘);
$response->header(‘Access-Control-Allow-Methods‘, ‘GET, POST, PATCH, PUT, OPTIONS‘);
$response->header(‘Access-Control-Allow-Credentials‘, ‘false‘);
return $response;
}
意思是允許所有的域都能訪問這個接口。但是這時候不能傳遞session和cookie,如果想要指定域名來訪問,就這樣寫:
$response->header(‘Access-Control-Allow-Origin‘, ‘http://mytest.com‘);
這個意思就是只允許http://mytest.com來訪問這個接口。
到這裏還沒完,中間件建立了,我們還要加到\app\Http\Kernel.php
裏面去,不然不能生效。
這時候就有選擇了,加到全局還是routeGroup?這個就取決於你的應用了,如果你的應用完全是接口,而且都是跨域,name就加到global那裏去。如下圖所示:
如果你是某幾個接口需要跨域,就寫到下面那個routeMiddle裏面去。
然後用的時候就在路由裏面加上這個中間件的別名即可。
這個方法比較簡單直接,但是有個缺陷,如果我要多個域名使用接口,並不是所有的,因為*太過open,一個域名又太過死板。怎麽辦,那就繼續往下看。
第三個方法:
在服務器端做文章,直接對來訪的域名進行過濾,只允許指定的一些域名來訪問這些接口。
With .htaccess you can do it like this:
# ----------------------------------------------------------------------
# Allow loading of external fonts
# ----------------------------------------------------------------------
<FilesMatch "\.(ttf|otf|eot|woff)$">
<IfModule mod_headers.c>
SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.net|dev02.otherdomain.net)$" AccessControlAllowOrigin=$0
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
</IfModule>
</FilesMatch>
這個我沒有測試過,這個需要在程序裏面允許所有的,即Access-Control-Allow-Origin‘, ‘*‘
,但是在服務器上只允許部分域名訪問。
參考鏈接:
https://stackoverflow.com/questions/1653308/access-control-allow-origin-multiple-origin-domains
https://stackoverflow.com/questions/25309318/best-method-access-control-allow-origin-multiple-origin-domains
總結:親測第一種方法是可行的,僅供參考。
laravel 5.5 oauth2.0 跨域問題解決方案