使用前后端分離(前端使用vue燕雁,react應(yīng)該也類似)的項目都離不開跨域問題诞丽,反反復(fù)復(fù)的經(jīng)歷過好幾次后,決定將目前最常用的三種解決方法做下記錄拐格,以免后面又在這一部分浪費(fèi)過多時間僧免。
1、 使用webpack提供的devServer來解決開發(fā)環(huán)境中跨域問題捏浊。這里用vue cli3創(chuàng)建的項目進(jìn)行說明
注意懂衩,這里僅限于開發(fā)環(huán)境,因為換到線上環(huán)境后金踪,我們會對vue項目進(jìn)行打包浊洞,這時候一般使用nginx進(jìn)行代理,就沒有devServer這個環(huán)境存在了胡岔。
- 打開項目目錄下的vue.config.js文件法希,沒有的話,新建一個靶瘸。配置內(nèi)容如下苫亦。
module.exports = {
devServer: {
host: '0.0.0.0', // 項目運(yùn)行的IP
port: 8080, // 項目運(yùn)行的端口
https: false,
// 開發(fā)環(huán)境跨域使用dev server解決
proxy: {
'/api': { // 匹配到/api的接口請求,我們下面將所有api請求全部加上api標(biāo)識
target: 'http://api-xxx.xxx.com', // 要轉(zhuǎn)發(fā)到的我們的api接口地址
changeOrigin: true,
pathRewrite: {
'^/api': '' // 這里將api這三個字符替換掉怨咪,變成我們接口真正的地址
}
}
},
}
}
target:轉(zhuǎn)發(fā)的后臺api地址
pathRewrite: 地址重寫規(guī)則
- 在項目目錄下新建環(huán)境文件.env.development屋剑,配置全局變量
VUE_APP_API_BASE_URL = '/api'
這里我們使用axios進(jìn)行請求,因此诗眨,在我們封裝的請求文件中設(shè)置如下:
axios.defaults.baseURL = process.env.VUE_APP_API_BASE_URL;
這樣的話唉匾,我們在接口請求中就不用了每個接口都手動加上/api這個標(biāo)識,axios請求會默認(rèn)加上該地址辽话。如我們的npm run server運(yùn)行時肄鸽,顯示:
則axios發(fā)出的api請求地址為 http://192.168.123.70:8080/api/接口地址,然后被devServer的進(jìn)行了代理油啤,將http://192.168.123.70:8080代理到了上面target配置的地址http://api-xxx.xxx.com典徘,且將api替換成了''(這個我們在用瀏覽器調(diào)試的時候是看不到轉(zhuǎn)換過程的,只會看到未轉(zhuǎn)換前的地址)益咬,這樣就可以不用改變我們的接口請求的代碼逮诲。
這里有個概念要說一下,上訴代理配置代理的源地址為http://192.168.123.70:8080幽告,如果我們在VUE_APP_API_BASE_URL里寫了我們接口的域名前綴梅鹦,如http://api-xxx.xxx.com/api,則不會被devServer的proxy代理到冗锁,導(dǎo)致代理無效齐唆。也就是說要從http://192.168.123.70:8080發(fā)出去的請求才會被代理到。
2冻河、使用nginx進(jìn)行代理轉(zhuǎn)發(fā)箍邮,可在線上環(huán)境使用
- 在nginx配置文件(代理vue項目訪問地址)中加上:
location /api {
rewrite ^(.*)\/api(.*)$ $1$2;
}
location /api {
add_header 'Access-Control-Allow-Origin' '*';
proxy_pass https://api-xxx.xxx.com;
}
3茉帅、在php項目中允許跨域請求(一勞永逸)
- 在請求的入口文件,如index.php里加入如下設(shè)置:
header('content-type:application:json;charset=utf8');
// 指定允許其他域名訪問
header('Access-Control-Allow-Origin:*');
// 響應(yīng)類型
header('Access-Control-Allow-Methods:POST, GET, OPTIONS');
// 響應(yīng)頭設(shè)置
header('Access-Control-Allow-Headers:authorization,x-requested-with,content-type');
- 使用框架的話锭弊,如laravel堪澎,可以新建一個中間件
php artisan make:middleware EnableCrossRequest
修改該文件,新建一個handle函數(shù)(如果沒有)味滞,加入:
public function handle($request, Closure $next)
{
$response = $next($request);
$origin = $request->server('HTTP_ORIGIN') ? $request->server('HTTP_ORIGIN') : '';
$allow_origin = [
'http://192.168.123.70:8080',
];
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, authenticated');
$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 $response;
}
然后在Http > Kernel.php中的變量$middleware中加入該中間件
這樣就大功告成樱蛤,如果遇到還有報錯,則可以看瀏覽器的console報錯信息剑鞍,看是否是header的返回字段中缺少什么昨凡,再進(jìn)行相應(yīng)的添加
參考:
https://learnku.com/articles/6504/laravel-cross-domain-solution
跨域原理解析,講的挺好的:https://juejin.im/post/5cef28af51882550d41745ea