Mr.Raindrop

Mr.Raindrop

一切都在无可挽回的走向庸俗。
twitter
github

【踩坑】Uniapp跨域問題的處理

跨域問題#

問題描述#

瀏覽器為了防止跨站請求偽造的攻擊,設定了同源策略機制。前端本地開發的 URL 大多是 “http+localhost + 端口”,這會產生跨域、cookie 種植和調用外部服務需要真實域名的問題。

同源策略是指兩個源相互之間只有同源,換句話說就是協議、域名和端口都一致,才能相互通信。這樣是為了保證請求的安全,減少惡意攻擊。

cookie 種植問題-- 如果前後端的鑑權涉及 cookie,那 localhost 之類的域名會影響 cookie 的種植。因為瀏覽器能否正確種植下 cookie,受到 domain 的影響。

調用外部服務需要真實域名。當我們項目調用外部服務時,經常需要完整的真實域名,比如微信登錄。此時本地開發沒有完整的真實域名,就無法在本地聯調。

為了驗證同源,瀏覽器會在所有請求中附帶一個特殊的請求一起發送給域信息接收伺服器。伺服器返回的 response 會附帶一個包含鍵為Access-Control-Allow-Origin的 header,用來標示什麼樣的源可以訪問伺服器的資源。通常分為兩種模式,當值為 * 時,伺服器允許任何源訪問自己的資源。另一種模式則是,指定的源的權限訪問。

前端 - 【譯】3 種解決 CORS 錯誤的方式與 Access-Control-Allow-Origin 的作用原理 - 個人文章 - SegmentFault 思否

處理方法#

  • 使用擴展插件,關閉瀏覽器的同源策略檢查。插件會在每次請求的 response 中加入一個Access-Control-Allow-Origin:*的 head。但許多時候並不是很管用。

  • 通過代理,作為客戶端和伺服器之間的中間人,這個代理服務會幫助前端 web app 發送請求,並且接收伺服器的返回數據再傳送給前端 web app。代理服務在原始的返回中,附加上一個Access-Control-Allow-Origin: * 的header。比如通過 Vue 或 React 等框架來配置 API 代理。本文嘗試通過 Vue 建立代理,將本地的數據通過代理端口發出,規避伺服器的同源檢查策略。Vue 的配置文件(vue.config.js)為:

    module.exports = {
    	devServer: {
            port: 12234,
    		open: true,
    		proxy: {
    			'/api1': { // 攔截以 本地頁面地址/api1 發出的請求
    				target: 'http://......', // 實際的後端地址
    				changeOrigin: true, // 這裡true表示實現跨域
    				secure: false, // 如果是https接口,需要配置這個參數
    				pathRewrite: {
    					'^/api1': '/' // 將/api1重寫為 / ;  伺服器最終收到的是統一從本地 12234 端口發出的數據
    				}
    			},
    			'/api2': { // 攔截以 本地頁面地址/api2 發出的請求
    				target: 'http://.....', //   另外一個後端地址
    				changeOrigin: true, // 這裡true表示實現跨域
    				secure: false, // 如果是https接口,需要配置這個參數
    				pathRewrite: {
    					'^/api2': '/'    
    				}
    			}
    		}
    	}
    };
    

    需要注意的是,Vue 的配置文件需要放在項目文件夾內,與 main.js 同級。

    vue:詳解 vue 中的代理 proxy_vue proxy-CSDN 博客

    什麼是跨域 | uni-app 官網 (dcloud.net.cn)

  • 建立自己的代理,同源策略只會作用於瀏覽器 - 伺服器之間,而不限制伺服器 - 伺服器的通信。

uniapp+uView 實現多個域名或端口的請求#

問題描述#

在項目代碼中,原先是參考Http 請求 | uView 2.0 - 全面兼容 nvue 的 uni-app 生態框架 - uni-app UI 框架 (uviewui.com)使用 uView 的 http 接口直接對訪問的參數和後端地址等的全局設置,並配置為插件在main.js中引入。但當需要訪問多個域名或是域名的不同端口時便無法使用這種全局設置。

解決方法#

將 uview 的 http 方法在封裝一層以設置不同的訪問域名或接口。

  • 在配置文件中,寫入需要訪問的域名或端口。

    	baseUrl_a: 'http://...',
    	baseUrl_b: 'http://...',
    
  • 在設置 uView http 的全局參數不設置其要訪問的 URL。

    uni.$u.http.setConfig((config) => {
    	// 域名設置
    	// config.baseURL = projectConfig.baseUrl;
        ... ...
    
  • 新建 js 文檔,根據不同的域名設置不同的訪問方法。

    // requestConfig.js
    const http = uni.$u.http;
    
    // 第一類接口的兩種方法
    export function http_a_get(path,params = ''){
    
    	return http.get(projectConfig.baseUrl_a + path, {params});
    }
    
    // 第二類接口的兩種方法
    export function http_b_get(path,params = ''){
    
    	return http.get(projectConfig.baseUrl_b + path, {params});
    }
    
  • main.js中引入添加到原型。

    import {http_a_get,http_b_get} from '..../reuquestConfig.js';
    Vue.prototype.$http_a_get = http_a_get;
    Vue.prototype.$http_b_get = http_b_get;
    
  • 在實際使用中,直接調用封裝好的函數。後需要添加新的端口及對應的方法需要在配置文件中添加端口並封裝所需要的方法最後在 main.js 中添加到原型。對於原有端口的修改,只需要在 URL 的配置文件中更改即可。

    export function getId(params) {
    	return http_a_get('/端口後的路徑', params);
    }
    
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。