1 我实现 laravel 跨域的时候,搜索了很多资料,以下罗列一下
前端ajax跨域问题分析
https://blog.csdn.net/bbirdsky/article/details/80561324 参考链接
被调用方Nginx及Apache设置方式
nginx添加如下配置,被调用方的Nginx服务器配置
server {
listen 80;
server_name xxx.com; // 服务端域名
location /{ // url转发
proxy_pass http://localhost:8080; // 将xxx.com转发至localhost:8080
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Max-Age 3600; // option请求缓存时间
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Headers $http_access_control_allow_headers;
if ($request_method = OPTIONS){
return 200; // 预检命令直接返回200
}
}
}
Apache配置修改与nginx思路一样,具体设值查询下apache的配置说明。
调用方解决方案 - 隐藏跨域
调用方的nginx配置如下:
server{
listen 80;
server_name ccc.com;
location / { // 将调用方的ccc.com转发至localhost:8081,调用方需要通过ccc.com访问
proxy_pass http://localhost:8081/; // 域名访问,通过客户端代理解决跨域问题
}
location /ajaxserver {
proxy_pass http://localhost:8080/test; // 将ajax请求统一转发至服务端
}
}
注意:此时调用方(客户端)的ajax代码,需要将请求url设置为相对路径,示例:
var baseUrl = "/ajaxserver";
// 正常情况应该是将baseUrl设置为服务端的绝对url,示例:localhost:8080
// 设置为/表示此路径为相对地址,即localhost:8081,这样来看所有的请求就是都走的8081的/ajaxserver转发,就不满足跨域条件
$.getJSON(baseUrl + "/getData").then(function(){});
2
参考链接
https://blog.csdn.net/zhezhebie/article/details/78068009
https://blog.csdn.net/root_miss/article/details/82740399
https://blog.csdn.net/woqianduo/article/details/84141395
以下,解决 option 请求
https://blog.csdn.net/qq_36427770/article/details/83276478
http://www.voidcn.com/article/p-azjhzrve-btr.html
解决跨域,有3个方法
https://blog.csdn.net/zhezhebie/article/details/78068009
1 使用中间件
参考链接
https://www.cnblogs.com/sai564/p/6259856.html?utm_source=itdadao
https://www.cnblogs.com/feiffy/p/9765316.html
https://blog.csdn.net/zq199692288/article/details/86605734
https://blog.csdn.net/qq_41901534/article/details/106247005
设置一个取得CSRF_TOKEN的路由
在laravel的routes目录下的入口路由中设置,一般默认是web.php,具体还是根据自己项目来。代码如下:
Route::get('/token', function () {
return csrf_token();
});
这是前端先GET请求后端建立的CSRF_TOKEN,再添加至头部信息中进行验证。
2 Laravel CORS 插件
https://blog.csdn.net/weixin_45175247/article/details/107079609
https://www.jianshu.com/p/1bae1d6a03b2?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
https://blog.csdn.net/qq_27295403/article/details/102619776
过程中间,报错 1
Response to preflight request doesn‘t pass access control check: It does not have HTTP ok status.
解决办法
参考 https://blog.csdn.net/HOOLOO/article/details/79121094
web.php 中,添加下面方法,可以直接捕获所有options路由,统一处理。
Route::options('{all}', function () {
$response = Response::make('OK');
$response->header('Access-Control-Allow-Origin', '*');
$response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept, Authorization,X-Auth-Token, X-Requested-with');
$response->header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE');
$response->header('Access-Control-Allow-Credentials', 'true');
$response->header('X-Content-Type-Options', 'nosniff');
$response->header('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT');
$response->header('Last-Modified', gmdate("D, d M Y H:i:s") . " GMT");
$response->header('Cache-Control', 'no-cache, must-revalidate');
$response->header('Pragma', 'no-cache');
return $response;
});
总结:
只要是带自定义header的跨域请求,在发送真实请求前都会先发送OPTIONS请求,浏览器根据OPTIONS请求返回的结果来决定是否继续发送真实的请求进行跨域资源访问。所以复杂请求肯定会两次请求服务端。
2 报错 Request header field Authorization is not allowed by Access-Control-Allow-Headers
参考
https://blog.csdn.net/root_miss/article/details/82740399
添加 header 头部信息
3 报错 419 unknown status
找到 VerifyCsrfToken.php文件(app/http/middleware)添加如下方法
//可以进行判断,判断域名,ip 进行条件判断
public function handle($request, \Closure $next)
{
// 使用CSRF
//return parent::handle($request, $next);
// 禁用CSRF
return $next($request);
}
或者
protected $except = [
// 'activity/mod/activity' // 免除对某路由的过滤
// 'http://www.ya.com/activity/mod/activity' // 免除对某路由的过滤
// 'http://www.ya.com/*' // 免除对某路由的过滤
];
4 我的解决办法
之前已经有了 cors 插件,但不是我写的,一直报错,我又自定义了中间件
\App\Http\Middleware\PreflightResponse::class,
中间件内容
<?php
namespace App\Http\Middleware;
use Closure;
class PreflightResponse
{
public function handle($request, Closure $next, $guard = null)
{
// $response = $next($request);
// $origin = $request->server('HTTP_ORIGIN') ? $request->server('HTTP_ORIGIN') : '';
$origin = $_SERVER['REMOTE_ADDR'] ? $_SERVER['REMOTE_ADDR'] : '';
$allow_origin = [
'http://localhost:8000',
'http://localhost:80',
'http://www.testyb.com:80',
'http://www.testyb.com',
];
if($request->getMethod() == 'OPTIONS' || $request->getMethod() == 'POST' ){
$origin = $request->header('ORIGIN', '*');
header("Access-Control-Allow-Origin: $origin");
// header("Access-Control-Allow-Origin: http://www.testyb.com");
// header("Access-Control-Allow-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, Cookie,OPTIONS,X-CSRF-TOKEN');
return $next($request);
}
header("Access-Control-Allow-Origin: http://www.testyb.com");
// header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");
header('Access-Control-Allow-Methods: *');
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, Cookie,OPTIONS,X-CSRF-TOKEN');
header('Access-Control-Request-Headers: Origin, Access-Control-Request-Headers, SERVER_NAME, Access-Control-Allow-Headers, cache-control, token, X-Requested-With, Content-Type, Accept, Connection, User-Agent, Cookie,OPTIONS,X-CSRF-TOKEN');
return $next($request);
}
}
同时,处理了option 请求
web.php 中
Route::options('{all}', function () {
$response = Response::make('OK');
$response->header('Access-Control-Allow-Origin', '*');
$response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept, Authorization,X-Auth-Token, X-Requested-with');
$response->header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE');
$response->header('Access-Control-Allow-Credentials', 'true');
$response->header('X-Content-Type-Options', 'nosniff');
$response->header('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT');
$response->header('Last-Modified', gmdate("D, d M Y H:i:s") . " GMT");
$response->header('Cache-Control', 'no-cache, must-revalidate');
$response->header('Pragma', 'no-cache');
return $response;
});
重点,针对报错信息,对症解决,主要在于请求头和返回头,并laravel中有csrf认证,需要处理,
另外,我做的是,网站 a 请求 网站 b,返回1个html页面,页面中包含 ajax请求
返回页面之后,ajax请求的url,变了,成了请求网站a ,报错,404
改成下面这样,就解决了,请求到了原来网站 b 路径
url: "{{url('activity/mod/activity')}}",