参考博客 :什么是跨域?跨域解决方法_越努力,越幸运!-CSDN 博客_跨域
一、为什么会出现跨域问题
出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的 javascript 脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
二、什么是跨域
当一个请求 url 的协议、域名、端口三者之间任意一个与当前页面 url 不同即为跨域
跨域解决方案
创建一个中间件
php artisan make:middleware EnableCrossRequestMiddleware.php
在中间件内
public function handle(Request $request, Closure $next) | |
{ | |
$response=$next($request); | |
$origin = $request->server('HTTP_ORIGIN') ? $request->server('HTTP_ORIGIN') : ''; | |
$allow_origin = [ | |
'http://localhost:8000', | |
]; | |
if(in_array($origin,$allow_origin)){ | |
$response->header('Access-Control-Allow-Origin', $origin); | |
$response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Cookie, X-CSRF-TOKEN, Accept, Authorization, X-XSRF-TOKEN'); | |
$response->header('Access-Control-Expose-Headers', 'Authorization, authenticated'); | |
$response->header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, OPTIONS'); | |
$response->header('Access-Control-Allow-Credentials', 'true'); | |
} | |
return $next($request); | |
} |
$allow_origin
数组变量就是你允许跨域的列表了,可自行修改。
在 Kernel.php 文件内注册
protected $routeMiddleware = [ | |
'auth' => \App\Http\Middleware\Authenticate::class, | |
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, | |
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, | |
'can' => \Illuminate\Auth\Middleware\Authorize::class, | |
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, | |
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, | |
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, | |
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, | |
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, | |
'pro'=>EnableCrossRequestMiddleware::class | |
]; |
一定不要忘了路由使用中间件
Route::group(['middleware'=>'pro','prefix'=>'v2','namespace'=>'Api',],function (){ | |
}); |
也可以内核文件注册该中间件
protected $middleware = [ | |
App\Http\Middleware\EnableCrossRequestMiddleware::class, | |
]; |
在App\Http\Kernel
类的$middleware
属性添加,这里注册的中间件属于全局中间件
。
有时候返回的不是 laravel 的 response 对象而是 Symfony 的 response,所以会报 $response->header 方法找不到,所以添加 header 的方法要简单改一下,可以拼好一个数组直接调用一次,
$response->headers->add(['Access-Control-Allow-Origin' => $origin]); | |
$response->headers->add(['Access-Control-Allow-Headers' => 'Origin, Content-Type, Cookie,X-CSRF-TOKEN, Accept,Authorization']); | |
$response->headers->add(['Access-Control-Expose-Headers' => 'Authorization,authenticated']); | |
$response->headers->add(['Access-Control-Allow-Methods' => 'GET, POST, PATCH, PUT, OPTIONS']); | |
$response->headers->add(['Access-Control-Allow-Credentials' => 'true']); |
或者handle里直接写
public function handle($request, Closure $next) | |
{ | |
header("Access-Control-Allow-Origin: *"); | |
$headers = [ | |
'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE', | |
'Access-Control-Allow-Headers'=> 'Content-Type, X-Auth-Token, Origin' | |
]; | |
$response = $next($request); | |
foreach($headers as $key => $value) | |
$response->header($key, $value); | |
return $response; | |
} |