㈠ 後端解決前端跨域請求問題
場景:前後端分離,頁面和後端項目部署在不同伺服器,出現請求跨域問題。
原因:CORS:跨來源資源共享(CORS)是一份瀏覽器技術的規范,提供了 Web 服務從不同網域傳來沙盒腳本的方法,以避開瀏覽器的同源策略,是 JSONP 模式的現代版。與 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以讓網頁設計師用一般的 XMLHttpRequest,這種方式的錯誤處理比JSONP要來的好,JSONP對於 RESTful 的 API 來說,發送 POST/PUT/DELET 請求將成為問題,不利於介面的統一。但另一方面,JSONP 可以在不支持 CORS 的老舊瀏覽器上運作。不過現代的瀏覽器(IE10以上)基本都支持 CORS。
預檢請求(option):在 CORS 中,可以使用 OPTIONS 方法發起一個預檢請求(一般都是瀏覽檢測到請求跨域時,會自動發起),以檢測實際請求是否可以被伺服器所接受。預檢請求報文中的 Access-Control-Request-Method 首部欄位告知伺服器實際請求所使用的 HTTP 方法;Access-Control-Request-Headers 首部欄位告知伺服器實際請求所攜帶的自定義首部欄位。伺服器基於從預檢請求獲得的信息來判斷,是否接受接下來的實際請求。
解決方案:
1、創建一個過濾器,過濾options請求。
package com.biz.eisp.sci.util;
import org.apache.commons.httpclient.HttpStatus;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 解決跨域問題
*
*/
public class CorsFilterimplements Filter {//filter 介面的自定義實現
public void init(FilterConfig filterConfig)throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
response.setHeader("Access-Control-Allow-Origin", "*");
if ("OPTIONS".equals(request.getMethod())){//這里通過判斷請求的方法,判斷此次是否是預檢請求,如果是,立即返回一個204狀態嗎,標示,允許跨域;預檢後,正式請求,這個方法參數就是我們設置的post了
response.setStatus(HttpStatus.SC_NO_CONTENT); //HttpStatus.SC_NO_CONTENT = 204
response.setHeader("Access-Control-Allow-Methods", "POST, GET, DELETE, OPTIONS, DELETE");//當判定為預檢請求後,設定允許請求的方法
response.setHeader("Access-Control-Allow-Headers", "Content-Type, x-requested-with"); //當判定為預檢請求後,設定允許請求的頭部類型
response.addHeader("Access-Control-Max-Age", "1"); // 預檢有效保持時間
}
filterChain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
2、修改web.xml文件
<filter>
<filter-name>cors</filter-name>
<filter-class>com.biz.eisp.sci.util.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/* </url-pattern>
</filter-mapping>
3、spring-mvc.xml添加HttpRequestHandlerAdapter http請求處理器適配器。
HttpRequestHandlerAdapter作為HTTP請求處理器適配器僅僅支持對HTTP請求處理器的適配。它簡單的將HTTP請求對象和響應對象傳遞給HTTP請求處理器的實現,它並不需要返回值。它主要應用在基於HTTP的遠程調用的實現上。
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
㈡ 瀏覽器跨域及其解決方案
title: 瀏覽器跨域及其解決方案
author: May
date: 20220428</pre>
什麼是跨域跨域的表現解決跨域問題- 瀏覽器設置(不推薦)- 前端的非正統解決方式- CORS(跨域資源共享)- 配置nginx反向代理
跨域 出於瀏覽器的同源策略限制, 同源 是指協議、域名、埠都一樣, 同源策略(Sameoriginpolicy) 是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響。
調用頁面時介面數據不返回,控制台中會有紅色的報錯信息中有類似於 CORS policy 關鍵字。另外,在最新谷歌瀏覽器中,會有提出類似於loaded over HTTPS此種關鍵字,均可以考慮為跨域導致。
[圖片上傳失敗...(image-26deed-1651135597111)]
tips: 有的時候後台小夥伴使用postman測試好的介面,前端不可以使用,原因就是postman不是瀏覽器,不會有同源限制,同理移動設備app開發和小程序開發也不會有這個問題。這個不是前端bug,同源限制也不是一個不好的規則。
雖然跨域不是一個不好的事情,但是對於前後端分離的web開發來說確實需要解決的,大致的解決方案可分為:
直接從根源解決問題,讓瀏覽器安全策略不起作用。這個方法雖然可以解決問題但是不現實。
官方正統解決方案, CORS規范 允許伺服器向瀏覽器返回一些HTTP Headers,瀏覽器可以基於這些HTTP Headers來決定是否突破SOP的限制。需要後端配合,瀏覽器需要什麼,介面服務給什麼。
nginx是一個高性能的HTTP和反向代理web伺服器,nginx用來解決跨域問題的原理與 前端非正統解決方式 的 proxy 的思路是一致的。項目請求介面由nginx服務發出,獲取到的數據再經由nginx傳遞給前端項目,這樣前端的請求其實都是由nginx處理的,就沒有跨域發生了。
㈢ web前端跨域的一些解決方案
沒有歸納之前對跨域的一些說法是模糊的,什麼jsonp啊,跨域原理啊,心裡只有一個大概的說法,知道這個東西,然後用的時候直接網路Ctrl+C,後來閑下來決定整理一波這些知識點,需知其所以然。
那麼,其實這是瀏覽器對我們的一種保護機制,把壞人擋在門外。那麼,問題來了,我們怎麼確定門外的人到底是好人還是壞人呢?瀏覽器關上了壞人的一扇門,留給了我們好人一扇窗。
JSONP跟JSON沒有關系..就好像JavaScript和Java一樣
瀏覽器對script、img(這些標簽的請求方式都是 GET ,所以jsonp不支持 POST )這種標簽沒有限制,我們就可以這樣干
因此,實現CORS通信的關鍵是伺服器。只要伺服器實現了CORS介面,就可以跨源通信。
伺服器端對於CORS的支持,主要就是通過設置 Access-Control-Allow-Origin 來進行的。如果瀏覽器檢測到相應的設置,就可以允許Ajax進行跨域的訪問。 更多有關跨域資源共享 CORS 的知識
瀏覽器中可以查看對應的響應頭,舉個例子,如下
服務端允許CORS,服務端需要針對介面設置的一系列響應頭 (Response Headers)
1.簡單請求
目前大多數情況都採用這種方式。簡單請求只需要設置 Access-Control-Allow-Origin 即可。滿足以下兩個條件,就屬於簡單請求。
2.非簡單請求
非簡單請求會發出一次預檢測請求,返回碼是204,預檢測通過才會真正發出請求,這才返回200。來看栗子:
非簡單請求需要根據不同情況配置不同的響應頭,一系列響應頭配置項見上方
這個說法相信不陌生,我們依然使用前端域名請求,然後有一個 中介商---代理 把這個請求轉發到真正的後端域名上,那也就不存在跨域問題了。
比較普遍的Nginx,簡單的配置一下就可以了。了解更多的配置信息: nginx詳解
然後前端這邊的請求地址是 http://localhost:9099/api/xxx ,然後Nginx監聽到地址是 localhost:9099/api 的請求,就幫我們轉發到真正的服務端地址 http://.com
CORS與JSONP的使用目的相同,但是比JSONP更強大。JSONP只支持GET請求,CORS支持所有類型的HTTP請求。JSONP的優勢在於支持老式瀏覽器,以及在服務端同意jsonp方式時,可以向不支持CORS的網站請求數據。Nginx可以說是最方便的,不過需要部署Nginx才行,需要對伺服器有一定的理解,不太適合剛入門的同學,當然也可以請後台同學幫忙部署。
window.postMessage(data,origin) 是 HTML5 的一個介面,專注實現不同窗口不同頁面的跨域通訊。
現在是這么一個情況,由於同源策略的限制下, a.html 不能操作iframe( b.html )裡面的dom,那麼使用postMessage就可以解決這一情況
然後 b.html 頁面通過message事件監聽並接受消息:
這種方式只適合主域名相同,但子域名不同的iframe跨域。
比如主域名是 http://.com/:8888 ,子域名是 http://child..com/:8888 ,這種情況下給兩個頁面設置相同的document.domain即document.domain = .com 就可以訪問各自的window對象了。
前端跨域整理
不要再問我跨域的問題了
㈣ 前端項目線上如何做跨域
前端頁面被跨域限制了,說明不同源。 這個時候可以找一台跟後台介面同源的伺服器用 nginx 來做介面轉發。
以一個 vue 項目為例,在開發過程中,開發者可以主動去配合 dev 的 proxyTable, 本質上是本地起了一個 node 服務(express)來做轉發到 localhost, 因為跨域是會存在於瀏覽器。 而發布到線上去之後,很可能由於 dev 環境下對每一個介面請求都攜帶了 /api 前綴,這對我們很友好。
nginx 配置:
其中配置二和配置三,本質上是一樣的(使用 ip 和域名)ip 後面有沒有 / 是由區別的,有 / 表示轉發請求之後,/api 後面的內容才會被轉發,相當於 url 是被截斷的,正好我們需要這種形式,因為 /api 是我們添加的虛擬的 url 部分。
詳情可以參考 https://www.cnblogs.com/lemon-le/p/7800879.html 或者 《nginx 高性能 Web 伺服器詳解》
㈤ 使用nginx代理解決跨域問題
先說說跨域這事情吧。早在13年,我剛接觸前端開發的時候就遇到了跨域,那時候剛開始流行前後端分離。解決跨域就是直接用get jsonp。還是小白的我,也沒有去想跨域的其它解決方式和為什麼要採用這種解決方式。
最近,做一個二次開發的項目,也碰到了用網頁請求http post,瀏覽器跨域,不能獲取返回數據的問題,所以再次來梳理下這個跨域,為什麼最後選擇了nginx代理。
首先,什麼是跨域呢?首先需要了解的是同源和跨源的概念。對於相同源,其定義為:如果協議、埠(如果指定了一個)和主機對於兩個頁面是相同的,則兩個頁面具有相同的源。 只要三者之一任意一點有不同,那麼就為不同源。 同源策略限制從一個源載入的文檔或腳本如何與來自另一個源的資源進行交互。這是一個用於隔離潛在惡意文件的關鍵的安全機制。當一個資源從與該資源本身所在的伺服器的域或埠不同的域或不同的埠請求一個資源時,資源會發起一個跨域 HTTP 請求。跨域不一定是瀏覽器限制了發起跨站請求,而也可能是跨站請求可以正常發起,但是返回結果被瀏覽器攔截了。 簡單的來說,出於安全方面的考慮,頁面中的JavaScript無法訪問其他伺服器上的數據,即「同源策略」。而跨域就是通過某些手段來繞過同源策略限制,實現不同伺服器之間通信的效果。
跨域的解決方案也有很多種。
類型一:有些瀏覽器可以設置 ,降低它的安全性。但是對於一個網站,要求設置瀏覽器是不切合實際的。
類型二:直接用form方式 ,這種情況下不是ajax請求,而是直接訪問目標地址了,不存在跨域問題,但是這個頁面已經跳轉了。而我們想實現的只是取另外一個地址的數據到本地顯示而已。
類型三:服務端語言是能夠處理的情況下。
1、CORS 是一個W3C標准,全稱是」跨域資源共享」(Cross-origin resource sharing)。它允許瀏覽器向跨源伺服器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。跨域資源共享( CORS )機制允許 Web 應用伺服器進行跨域訪問控制,從而使跨域數據傳輸得以安全進行。其需要服務端和客戶端同時支持。
對於簡單請求,瀏覽器直接發出CORS請求。具體來說,就是在頭信息之中,增加一個Origin欄位。如果Origin指定的源,不在許可范圍內,伺服器會返回一個正常的HTTP回應。瀏覽器發現,這個回應的頭信息沒有包含Access-Control-Allow-Origin欄位(詳見下文),就知道出錯了,從而拋出一個錯誤,被XMLHttpRequest的onerror回調函數捕獲。注意,這種錯誤無法通過狀態碼識別,因為HTTP回應的狀態碼有可能是200。如果Origin指定的域名在許可范圍內,伺服器返回的響應,會多出幾個頭信息欄位。 Access-Control-Allow-Origin 該欄位是必須的。它的值要麼是請求時Origin欄位的值,要麼是一個*,表示接受任意域名的請求。 Access-Control-Allow-Credentials 該欄位可選。 Access-Control-Expose-Headers 該欄位可選。
可以說這種辦法主要在header上下功夫,設置Access-Control-Allow-Origin為所有*允許訪問。雖然說它支持所有的請求方式,post,delete,put等等,但是它不能兼容ie6,7等等。
例如下圖的nodejs express 例子:
2、服務端的http ajax請求全部改為 get jsonp方式 。該方式能夠兼容老式瀏覽器。
3、iframe window.name 這種傳值得方式很巧妙,兼容性也很好。但是在要訪問數據的地址那個伺服器要有一個空的中間頁面拿來用。
4、postMessage , html5 window.postMessage。 同iframe window.name有點像,也是需要服務端有個空的html拿來接收數據。而且現在的postMessage兼容性也不好。
5、document.domain 修改為頂級域名。
6、 WebSocket ,協議不實行同源政策,只要伺服器支持,就可以通過它進行跨源通信。
類型四:不是簡單的前後端。假如有個第三方的api,自己有一個網站前端,一個網站後端。
1、自己的網站端和後端源碼放在同一個服務埠和目錄下,不存在跨域。當直接用網站前端的http訪問第三方api,瀏覽器跨域。此時,改為由網站後端的服務端語言訪問,做個中間人,將訪問的數據給網頁前端。
2、網站前端和後端不是同源的,採用以上的跨域方案,譬如CORS。同樣的網站後端做中間人,訪問第三方api,再轉給網頁前端。
3、使用nginx 反向代理解決跨域問題。 網站前端訪問nginx服務的地址,nginx設置代理地址為訪問第三方api地址,當訪問代理地址的時候,瀏覽器訪問的是nginx服務的地址,實際是訪問第三方api地址。
注意:此時,如果目錄下有個proxy.html,因為設置代理地址是/proxy,碰到這個地址就被轉到」https://192.168.18.175:8088/api/v1.0.2/「,所以要訪問proxy.html是訪問不到的。
4、使用nginx代理地址是解決生產環境發布的問題了,那麼我在開發的時候使用angular這樣需要打包的框架怎麼辦呢。當然在開發環境下,angular也是由類似代理地址的解決方案的。
(1)創建配置代理文件:假設後端服務的訪問地址為http://192.168.19.175:8088/api/v1.0.2/login,我們可以創建一個proxy.conf.json文件,放在package.json同目錄下。
(2)改寫package.json文件 ,採用--proxy-config命令(angular自帶的命令)。
(3)ajax訪問代理地址
此時, 執行 npm start ,即可發現,瀏覽器訪問http://localhost:4200/api/v1.0.2/login 的同源地址,實際上是訪問http://192.168.18.175:8088/api/v1.0.2/login.
angular在開發環境下代理地址的方法類似在生產環境下使用的nginx代理。但是測試angular是有一個/api代理地址的巧合。剛好第三方api上面的地址有個api,才能使用這個地址,並且能夠簡寫一個api,才能成功訪問,如果更改為其它的,譬如proxy,就測試失敗。而且proxy.conf.json文件下的設置也只能是域名和埠。所以,本人測試,這或許是個巧合或者是缺陷。
五、其它
當然,跨域這個算是歷史性的問題,以後也會存在這個問題。除了上面各種方法,以及根據各種方法使用的場合,還有許多其它的方法。例如各大流行框架react,vie應該也有像angular一樣,能夠處理跨域的開發環境方案,接下來,還是要繼續學習和積累。
㈥ 前端跨域解決 (vscode live server proxy 代理)
這個顯然是處理前端跨域最優的方法了,在此記錄下來方便以後使用,附送scss 轉 css
使用 vscode IDE作為編寫工具
1.搜索並載入 vscode 插件 live server
2.要文件根目錄創建 ".vscode" 目錄
3.在 .vscode 目錄下創建settings.json
4.proxUri 為代理的目標地址
5.baseUri 識別代理的符號 (如下例中 baseUri: '/api', 則以"/api"開頭的網路請求都將被識別為需要代理轉發的地址,並把 『/api』重寫為空"")
1.ajax請求會受到瀏覽器同源策略的限制(同源 = 域名 + 埠 都一致)
2.ajax請求默認攜帶 同源下的所有cookie, 如果不做限制 a 去請求 b 的時候就等於把a所有的cookie 都告訴b。
3.同源下: 張三的網站只能訪問張三的內容如鞋子衣服吃飯等等,如果想訪問李四的,瀏覽器就不讓你幹了。如果充許這么乾的話,張三的cookie隱私將直接暴露給李四,李四有可能幹一些不懷好意的事情。
4.跨域情況:張三把錢都放在李四那裡,現在張三想去李四那邊取錢,這時候就需要跨域了。
5.跨域怎麼解決呢?接下來把解決問題的思路簡單描繪一下。
5.1:李四告訴全世界說我對錢不感興趣,只要我有,你們所有人都隨便來取。因此,當瀏覽器看到張三要取錢的人是李四這種慈善家,就不再攔著你了。
5.2:李四不是慈善家怎麼辦?於是張三這個時候就很討厭瀏覽器,想了個辦法繞過瀏覽器,然後另外找了個代理去跟李四取錢
5.2.1: 問題是繞過瀏覽器?怎麼繞呢? 於是張三自己建了個伺服器,每次要跟李四取錢的時候就欺騙瀏覽器說我要跟自己的伺服器取錢,瀏覽器這個時候也就不再攔著你了
5.2.2:當張三自己的伺服器接收到跟李四取錢任務後,就以proxy代理的身份向李四取錢,取完錢之後再通過瀏覽器給了張三
5.2.3:vscode 中的live server 插件裡面就這個代理向李四取錢的代理伺服器功能,本文settings.json 中包含了配置信息
6.當然還有一些很多牛叉的解決跨域的方法。若有興趣的同學可以一起研究探討。
㈦ 後端使用springboot+tio-http-server,前端使用element-ui+websocket,如何解決跨域問題後端已支持跨域
最便捷的還是使用nginx反向代理吧。
例如,假設後端的ip和埠號為:192.168.111.222:8080,前端的ip和埠號為:192.168.111.222:8001,此時前後端埠不一致導致跨域。
部署一個ngnix,修改ngnix安裝目錄下的/config/nginx.conf文件,剛安裝的ngnix的配置文件里默認應該為:
配置好ngnix後,你前端工程里訪問後端介面時,只需要將請求url修改為http://192.168.111.222:8001/api/即可。
例如你原來的登錄後端介面可能是訪問http://192.168.111.222:8080/login,你要修改為訪問http://192.168.111.222:8001/api/login
㈧ 前端跨域方式有哪些
處理跨域方法一——JSONP
1.JSONP原理
利用script元素的這個開放策略,網頁可以得到從其他來源動態產生的 JSON 數據。JSONP請求一定需要對方的伺服器做支持才可以。
2.JSONP和AJAX對比
JSONP和AJAX相同,都是客戶端向伺服器端發送請求,從伺服器端獲取數據的方式。但AJAX屬於同源策略,JSONP屬於非同源策略(跨域請求)
3.JSONP優缺點
JSONP優點是兼容性好,可用於解決主流瀏覽器的跨域數據訪問的問題。缺點是僅支持get方法具有局限性。
4.JSONP的流程(以第三方API地址為例,不必考慮後台程序)
聲明一個回調函數,其函數名(如fn)當做參數值,要傳遞給跨域請求數據的伺服器,函數形參為要獲取目標數據(伺服器返回的data)。
創建一個
伺服器接收到請求後,需要進行特殊的處理:把傳遞進來的函數名和它需要給你的數據拼接成一個字元串,例如:傳遞進去的函數名是fn,它准備好的數據是fn([{「name」:「jianshu」}])。
最後伺服器把准備的數據通過HTTP協議返回給客戶端,客戶端再調用執行之前聲明的回調函數(fn),對返回的數據進行操作。
處理跨域方法二——CORS
1.CORS原理
整個CORS通信過程,都是瀏覽器自動完成,不需要用戶參與。對於開發者來說,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感覺。因此,實現CORS通信的關鍵是伺服器。只要伺服器實現了CORS介面,就可以跨源通信。
2.CORS優缺點
CORS要求瀏覽器(>IE10)和伺服器的同時支持,是跨域的根本解決方法,由瀏覽器自動完成。
優點在於功能更加強大支持各種HTTP Method,缺點是兼容性不如JSONP。
處理跨域方法三——WebSocket
Websocket是HTML5的一個持久化的協議,它實現了瀏覽器與伺服器的全雙工通信,同時也是跨域的一種解決方案。WebSocket和HTTP都是應用層協議,都基於 TCP 協議。但是 WebSocket 是一種雙向通信協議,在建立連接之後,WebSocket 的 server 與 client 都能主動向對方發送或接收數據。同時,WebSocket 在建立連接時需要藉助 HTTP 協議,連接建立好了之後 client 與 server 之間的雙向通信就與 HTTP 無關了。
原生WebSocket API使用起來不太方便,我們使用Socket.io,它很好地封裝了webSocket介面,提供了更簡單、靈活的介面,也對不支持webSocket的瀏覽器提供了向下兼容。
處理跨域方法四——postMessage
如果兩個網頁不同源,就無法拿到對方的DOM。典型的例子是iframe窗口和window.open方法打開的窗口,它們與父窗口無法通信。HTML5為了解決這個問題,引入了一個全新的API:跨文檔通信 API(Cross-document messaging)。這個API為window對象新增了一個window.postMessage方法,允許跨窗口通信,不論這兩個窗口是否同源。postMessage方法的第一個參數是具體的信息內容,第二個參數是接收消息的窗口的源(origin),即"協議 + 域名 + 埠"。也可以設為*,表示不限制域名,向所有窗口發送。
㈨ 前端解決跨域都有哪些方法
什麼是跨域?
瀏覽器發送的請求地址(URL)與所在頁面的地址 不同(埠/協議/域名 其一不同)。簡言之,瀏覽器發出的請求url,與其所在頁面的url不一樣。此時,同源策略會讓瀏覽器拒收 伺服器響應回來的數據,報錯信息如下:
最常用的四種跨域解決方案
1.cors
cors跨域資源共享允許是在服務端"Access-Control-Allow-Origin"欄位設置的,當將cors設置為允許某個地址訪問時,該地址就可以跨域訪問這個伺服器地址。當cors設置為"*"時即允許所有地址訪問時,則表示所有地址都可以跨域訪問這個伺服器地址的資源。
2、 通過jsonp跨域
Jsonp是Json的一種「使用模式」,他就可以解決瀏覽器遇到的跨域問題,我們可以動態創建script,再請求一個帶參網址實現跨域通信。用Jsonp請求得到的是JavaScript,相當於直接用JavaScript解析。
3、postMessage跨域
在h5中新增了postMessage方法,postMessage可以實現跨文檔消息傳輸,我們可以通過Windows的message事件來監聽發送跨文檔消息傳輸內容。
4、proxy(代理)
原理:因為同源策略只是針對瀏覽器的安全策略,但是服務端並不受同源策略的限制,也就不存在跨域的問題。