1.创建中间件
# 1.可以通过php-cli命令行进行创建
php artisan make:middleware CoreHttp
# 2.也可以通过到app/Http/Middleware目录中进行创建
2.配置中间件加载(app/Http/Kernel.php)
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
// 全局中间件加载区
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
];
// 应用分组中间件加载区
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'cors', // todo 此处示例在api应用中进行加载
'throttle:60,1',
'bindings',
],
];
// 应用中间件预加载区
protected $routeMiddleware = [
'cors' => \App\Http\Middleware\CoreHttp::class, // 跨域
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
}
3.服务端跨域中间件的代码编写
<?php
namespace App\Http\Middleware;
use Closure;
class CoreHttp
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';//获取当前域名
// 非跨域请求
if (empty($origin)) {
return $response;
}
// todo 允许访问来源域名、允许访问路由(可写入框架配置文件中进行统一管理)
$allowOrigin = [
'http://test.laravel.com',
'http://test.laravel.cn',
];
/* 示例:
百分百匹配模式 api/user/list
模糊匹配模式 api/user/*
*/
$allowPath = [
'api/*'
];
// 判断是否为允许访问域名
if (in_array($origin,$allowOrigin)) {
$response->header('Access-Control-Allow-Origin', $origin); //允许所有资源跨域
// 判断是否为可访问路由
if (!$this->handle_request_paths($allowPath)){
return false;
}
}
$response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Cookie, Accept, Authorization, application/json , X-Auth-Token');//允许通过的响应报头
$response->header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, OPTIONS, DELETE');//允许的请求方法
$response->header('Access-Control-Expose-Headers', 'Authorization');//允许axios获取响应头中的Authorization
$response->header('Allow', 'GET, POST, PATCH, PUT, OPTIONS, delete');//允许的请求方法
$response->header('Access-Control-Allow-Credentials', 'true');//运行客户端携带证书式访问
return $response;
}
// todo 适用于各种框架调用
private function handle_request_paths($allowPaths)
{
$uri = $_SERVER['REQUEST_URI'];
$parseUrlInfo = parse_url($uri);
$path = $parseUrlInfo['path'];
// 匹配结果标识,默认可匹配
$isMatch = true;
if (!empty($allowPaths)) {
$isMatch = false;
if ($path !== '/') {
$path = ltrim($path,'/');
}
foreach ($allowPaths as $allowPath) {
// 不包含全部匹配
if (!strrpos($allowPath,'/*')) {
// 如果访问path与允许的path完全相同,则表示可访问
if ($path == $allowPath) {
$isMatch = true;
break;
}
} else {
// 包含全部匹配
$allowPath = rtrim($allowPath,'/*');
// 如果允许的path能在访问path字符串的最前处找到,则表示可访问
if (strpos($path,$allowPath) === 0) {
$isMatch = true;
break;
}
}
} unset($allowPath);
}
return $isMatch;
}
}