lumen使用CORS解決跨域問題

由於公司的業務是先後端分離,web前端和後端接口域名不一樣,因此存在跨域問題,開始使用的是jsonp解決,可是由於接口風格是rest的,還有delete、put等請求,jsonp就不夠用了(涉及HTTP簡單請求和複雜請求,這裏有詳細介紹),所以就找到了CORS跨域解決方案。原理過長,因此本篇文章只寫服務端代碼實現部分。php

代碼實現

app/Http/Middleware 裏新建一個CorsMiddleware.php,並寫入以下代碼:html

<?php
/*
 * Author:xx_lufei
 * Time:2016年11月3日13:15:51
 * Note:Access Control Headers.
 */

namespace App\Http\Middleware;


use Illuminate\Http\Request;
use Illuminate\Http\Response;

class CorsMiddleware
{
    private $headers;
    private $allow_origin;

    public function handle(Request $request, \Closure $next)
    {
        $this->headers = [
            'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE',
            'Access-Control-Allow-Headers' => $request->header('Access-Control-Request-Headers'),
            'Access-Control-Allow-Credentials' => 'true',//容許客戶端發送cookie
            'Access-Control-Max-Age' => 1728000 //該字段可選,用來指定本次預檢請求的有效期,在此期間,不用發出另外一條預檢請求。
        ];

        $this->allow_origin = [
            'http://localhost',
            'http://192.168.1.12:8080'
        ];
        $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';

        //若是origin不在容許列表內,直接返回403
        if (!in_array($origin, $this->allow_origin) && !empty($origin))
            return new Response('Forbidden', 403);
        //若是是複雜請求,先返回一個200,並allow該origin
        if ($request->isMethod('options'))
            return $this->setCorsHeaders(new Response('OK', 200), $origin);
        //若是是簡單請求或者非跨域請求,則照常設置header
        $response = $next($request);
        $methodVariable = array($response, 'header');
        //這個判斷是由於在開啓session全局中間件以後,頻繁的報header方法不存在,因此加上這個判斷,存在header方法時才進行header的設置
        if (is_callable($methodVariable, false, $callable_name)) {
            return $this->setCorsHeaders($response, $origin);
        }
        return $response;
    }

    /**
     * @param $response
     * @return mixed
     */
    public function setCorsHeaders($response, $origin)
    {
        foreach ($this->headers as $key => $value) {
            $response->header($key, $value);
        }
        if (in_array($origin, $this->allow_origin)) {
            $response->header('Access-Control-Allow-Origin', $origin);
        } else {
            $response->header('Access-Control-Allow-Origin', '');
        }
        return $response;
    }
}

經過數組的形式實現容許多個origin。前端

boostrap/app.php 裏註冊一下全局中間件便可完成web

$app->middleware([
 \App\Http\Middleware\CorsMiddleware::class,
]);

注意

默認狀況下,cookie是不包括在CORS請求中的,若是服務器要接受cookie,必須設置json

'Access-Control-Allow-Credentials'=> 'true'

若是不須要cookie,則必須刪除該字段,改false是沒用的,這個值只能是true。後端

若是是更復雜的業務需求,能夠把method提出來作相應的邏輯判斷。跨域

與JSONP的比較

CORS與JSONP的使用目的相同,可是比JSONP更強大。
JSONP只支持GET請求,CORS支持全部類型的HTTP請求。JSONP的優點在於支持老式瀏覽器,以及能夠向不支持CORS的網站請求數據。數組

原文地址:https://www.jianshu.com/p/ce6a14a4a270瀏覽器

相關文章
相關標籤/搜索