-
1 # 爻信社交
-
2 # 開悟科技
何在伺服器上部署一個前後端分離的專案並解決跨域問題
以後端為spring-boot與前臺為vue的專案舉例。
一.給伺服器安裝相應的需求環境。
1.安裝jdk。
安裝方式可自行百度,推薦使用yum安裝,安裝完成後配置環境即可。
2.安裝nginx。代理伺服器,安裝方式可自行百度,yum應該也是可以安裝的。
二.部署後臺程式碼。
1.這裡採用IDEA作為開發工具,只要通過maven的打包操作package在target那裡找到jar包即可。
2.將jar包複製到伺服器上任意目錄。
3.開啟伺服器控制終端,cd到jar包所在目錄。
執行java -jar XXXXXX.jar 即可。
當然這樣是沒法進行另外的操作除非退出來ctrl+C,可以加個停止符號。
java -jar XXXXXX.jar &即可。
三.執行sql檔案。
在伺服器上安裝並啟動mysql服務,具體可自行百度。
然後進入mysql,將專案的sql檔案放入伺服器並執行即可。
需要注意的是。mysql在linux下和windows下有所區別,它的資料庫名是區分大小寫的,記住你的資料庫名要和你後臺程式碼中alidruid的jdbc配置要完全相同。
四.部署前端專案。
1.先進入本地的前端專案,開啟config/index.js
配置assetsPublicPath這個屬性值為‘/’注意這個屬性值要出現兩次,需要更改兩次。
同時記住dev配置下的proxyTable屬性,即後端介面埠的別名,我這裡是/api/
2.這裡是webpack打包的,開啟控制檯。
cd到本地的專案目錄下。
執行npm run build。
在本地前端目錄下可以看到多了一個dist資料夾,複製它。
3.把dist資料夾複製到伺服器上的任意目錄。
4.配置nginx配置使其指向你前端的埠。
A.cd進nginx的配置檔案處
將nginx.conf和nginx.conf.default兩個檔案內的配置內容給註釋了,即每行前面加#,使用vim。
然後在conf.d下面新建一個配置檔案。
其中要注意的是。listen後面跟上你所部署的前端埠。
location後面配置上你所部署的前端靜態檔案後面所在的具體目錄注意root 後面的屬性一定要是dist的絕對路徑。
後面的一堆addheader可以不加。最後還有個location /api 這裡的api要看你後端介面的路徑具體別名。proxy_pass要看你後臺的埠號。
這裡一定要加,不然前端無法呼叫後臺的相應介面。
這裡是在用nginx進行反向代理解決跨域問題。
五.訪問部署好的網站。
將原來本地訪問的localhost改成你的伺服器的IP地址名即可。
如果出現了404的問題,根本原因肯定是跨域問題,即nginx沒有配置好。
如果出現了403的問題,根本原因肯定是config.js的問題或者nginx的location裡沒有指向正確的dist路徑。
————————————————
原文連結:https://blog.csdn.net/TateBrwonJava/java/article/details/80373913
-
3 # 俠夢的開發筆記
題主這個問題,相信是很多前後端開發者都會遇到的,在這裡我想從提出一個疑問的角度來回答。
為什麼postman調介面不會跨域而瀏覽器會?都在說跨域,為什麼postman能訪問介面,而瀏覽器就不行呢?這裡需要理解什麼是跨域,跨域是指的當前資源訪問其他資源時發起的http請求由於安全原因(由於同源策略,域名、協議。埠中只要有一個不同就不同源),瀏覽器限制了這些請求的正常訪問,特別需要注意的是這些發生在瀏覽器中。而通過postman等工具呼叫介面時,只是簡單的訪問一個資源,並不存在資源的相互訪問。知識預熱回撥函式這裡就不細講回撥函式啦,相信各位都能理解,用一個案例來說一下。“伺服器”和“客戶端”初次相識,相談甚歡,客戶端希望伺服器把一個叫json的東西給它,”伺服器“:你先忙著,我弄好了發給你,把你電話號碼(回撥函式)給我。跨域中的預檢請求即是指瀏覽器在真正傳送請求前,會先發送一個Options請求嗅探,請求成功後才會傳送真實的請求。問答三連:為什麼需要傳送預檢請求?是因為觸發了瀏覽器的安全校驗。為什麼請求會觸發安全校驗?因為當前請求是一個"複雜請求"。為什麼我的請求是“複雜的”?見下面解釋複雜和簡單請求簡單請求:請求方法是GET/HEAD/POST,並且contentType為text/plain、application/x-www-form-urlencoded、multipart/form-data。不滿足上述條件的視為複雜請求,開發中我們常觸發這個條件大多因為我們的請求的contentType設定的是application/json導致的。簡單請求如果設定了Authentication認證header也會讓請求“升級”為複雜請求。理解spring提供的@CrossOrigin註解@CrossOrigin可以放在某個方法上,或者放在類上,這樣對類中所有請求方法有效,指定能訪問的域集合,即是設定Access-Control-Allow-Origin。maxAge 屬性指定了預檢請求的快取時間,單位是秒。對應http的Access-Control-Max-Age屬性快取的內容為:Access-Control-Allow-Methods和Access-Control-Allow-Headers 提供的資訊。上面的例子在正常返回的json前面包裹了一個函式名,為的是能讓瀏覽器執行,如果不採用jsonp的方式,而是後端設定Access-Control-Allow-Origin,則請求到的不是一個標準json,所以我們需要改造一下,相容兩種方式。其他遇到的問題在解決跨域時,遇到這種錯誤,一般是前端沒有設定回撥函式,而後端返回了被回撥函式包裹的json.回撥函式未定義,請求後端介面的script標籤必須在宣告的回撥函式之後定義,否則會報錯。
-
4 # 淺談機械
跨域資源共享(CORS)是前後端分離專案很常見的問題,本文主要介紹當SpringBoot應用整合SpringSecurity以後如何解決該問題。
什麼是跨域問題
CORS全稱Cross-Origin Resource Sharing,意為跨域資源共享。當一個資源去訪問另一個不同域名或者同域名不同埠的資源時,就會發出跨域請求。如果此時另一個資源不允許其進行跨域資源訪問,那麼訪問的那個資源就會遇到跨域問題。
跨域問題演示及解決
我們使用mall專案的原始碼來演示一下跨域問題。此時前端程式碼執行在8090埠上,後端程式碼執行在8080埠上,由於其域名都是localhost,但是前端和後端執行埠不一致,此時前端訪問後端介面時,就會產生跨域問題。
此時發現呼叫登入介面時出現跨域問題。
新增GlobalCorsConfig配置檔案來允許跨域訪問。
package com.macro.mall.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; /** * 全域性跨域配置 * Created by macro on 2019/7/27. */@Configuration public class GlobalCorsConfig { /** * 允許跨域呼叫的過濾器 */ @Bean public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); //允許所有域名進行跨域呼叫 config.addAllowedOrigin("*"); //允許跨越發送cookie config.setAllowCredentials(true); //放行全部原始頭資訊 config.addAllowedHeader("*"); //允許所有請求方法跨域呼叫 config.addAllowedMethod("*"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); }}
發現需要登入認證的/admin/info介面的OPTIONS請求無法通過認證,那是因為複雜的跨越請求需要先進行一次OPTIONS請求進行預檢,我們的應用整合了SpringSecurity,對OPTIONS請求並沒有放開登入認證。
在SecurityConfig類的configure(HttpSecurity httpSecurity)方法中新增如下程式碼。
.antMatchers(HttpMethod.OPTIONS)//跨域請求會先進行一次options請求 .permitAll()
發現已經可以正常訪問。
先發起一次OPTIONS請求進行預檢
請求頭資訊:Access-Control-Request-Headers: content-type Access-Control-Request-Method: POST Origin: http://localhost:8090 Referer: http://localhost:8090/ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
響應頭資訊:Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: content-type Access-Control-Allow-Methods: POST Access-Control-Allow-Origin: http://localhost:8090 Cache-Control: no-cache, no-store, max-age=0, must-revalidate Content-Length: 0 Date: Sat, 27 Jul 2019 13:40:32 GMT Expires: 0 Pragma: no-cache Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers X-Content-Type-Options: nosniff X-Frame-Options: DENY X-XSS-Protection: 1; mode=block
請求成功返回狀態碼為200發起真實的跨域請求
請求頭資訊:Accept: application/json, text/plain, */* Content-Type: application/json;charset=UTF-8 Origin: http://localhost:8090 Referer: http://localhost:8090/ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 {username: "admin", password: "123456"} password: "123456" username: "admin"
響應頭資訊:Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: http://localhost:8090 Cache-Control: no-cache, no-store, max-age=0, must-revalidate Content-Type: application/json;charset=UTF-8 Date: Sat, 27 Jul 2019 13:40:32 GMT Expires: 0 Pragma: no-cache Transfer-Encoding: chunked Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers X-Content-Type-Options: nosniff X-Frame-Options: DENY X-XSS-Protection: 1; mode=block
請求成功返回狀態碼為200 -
5 # 阿鑽的生活日記
首先我們需要知道,什麼是跨域?
跨域,是指瀏覽器不能執行其他網站的指令碼。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript實施的安全限制。
那麼什麼是同源策略及其限制內容?
同源策略是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSRF等攻擊。所謂同源是指"協議+域名+埠"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。
同源策略限制了一下行為:
跨域解決方案1、 通過jsonp跨域
2、 document.domain + iframe跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 postMessage跨域
6、 跨域資源共享(CORS)
7、 nginx代理跨域
8、 nodejs中介軟體代理跨域
9、 WebSocket協議跨域
一般有上面這9種方案來解決,不賣關子,當前網際網路公司一般採用第6和第7種解決方案居多!下面就對這2個方案做一個闡述,其它解決方案可以做個瞭解即可。一、跨域資源共享(CORS)
CORS 需要瀏覽器和後端同時支援。IE 8 和 9 需要通過 XDomainRequest 來實現。
瀏覽器會自動進行 CORS 通訊,實現 CORS 通訊的關鍵是後端。只要後端實現了 CORS,就實現了跨域。
服務端設定 Access-Control-Allow-Origin 就可以開啟 CORS。 該屬性表示哪些域名可以訪問資源,如果設定萬用字元則表示所有網站都可以訪問資源。
雖然設定 CORS 和前端沒什麼關係,但是通過這種方式解決跨域問題的話,會在傳送請求時出現兩種情況,分別為簡單請求和複雜請求。
1) 簡單請求只要同時滿足以下兩大條件,就屬於簡單請求
條件1:使用下列方法之一:
GETHEADPOST條件2:Content-Type 的值僅限於下列三者之一:
text/plainmultipart/form-dataapplication/x-www-form-urlencoded請求中的任意 XMLHttpRequestUpload 物件均沒有註冊任何事件監聽器; XMLHttpRequestUpload 物件可以使用 XMLHttpRequest.upload 屬性訪問。
2) 複雜請求不符合以上條件的請求就肯定是複雜請求了。 複雜請求的CORS請求,會在正式通訊之前,增加一次HTTP查詢請求,稱為"預檢"請求,該請求是 option 方法的,通過該請求來知道服務端是否允許跨域請求。
後臺需做如下配置:
response.setHeader("Access-Control-Allow-Origin", "http://www.domain.com"); // 若有埠需寫全(協議+域名+埠)
response.setHeader("Access-Control-Allow-Credentials", "true");
二、nginx反向代理介面跨域跨域原理: 同源策略是瀏覽器的安全策略,不是HTTP協議的一部分。伺服器端呼叫HTTP介面只是使用HTTP協議,不會執行JS指令碼,不需要同源策略,也就不存在跨越問題。
實現思路:通過nginx配置一個代理伺服器(域名與domain1相同,埠不同)做跳板機,反向代理訪問domain2介面,並且可以順便修改cookie中domain資訊,方便當前域cookie寫入,實現跨域登入。
nginx具體配置:
最後通過命令列啟動nginx就可以了。
這兩個解決方案都可以,看各自公司選擇了,希望可以幫到您。
-
6 # iamjxc
基於nginx的反向代理功能,我們自己實現的反向代理類,直接整合在開發平臺裡。而且解決了自動登入目標伺服器,回撥客戶端等功能
-
7 # 前端達人
現在開發專案,大部分公司採用的都是前後端分離的方式進行開發,由於現在產品形態越來越多,網頁、手機端、桌面端等等,為了面對各種端,資料中心化、微服務概念的出現,我們為了整合這些服務,不得不去面對一個常見的問題——解決跨域請求的問題。
以前工作開發中,經常會有這樣的問題,前端工程師的前端頁面由於跨域問題報錯了,來協調後端開發人員解決,後臺開發人員還那解釋你來看我這邊的介面是正常的,應該是你的問題,這是前端開發人員的心頓時是崩塌的,如果你還不知道怎麼辦的時候,也許會默默的自己去尋找解決方案,一查解決方案,這個工作應該需要前後臺一起配合,你還得給後端開發人員去好說歹說,讓他們也看看一起解決。我很能理解作為前端的我們真是不容易啊。
關於跨域這個問題,不僅前端工程師需要了解,後端工程師也需要了解更應該重視,因為後面會提及到相關的解決方案,需要共同配合才能完成。藉著回答這個問題的機會,我來把跨域的相關內容進行系統的梳理,分享給大家。
跨域(CORS)——跨源資源共享。換成我們前端開發人員能理解的就是指瀏覽器不能執行其他網站的指令碼。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript的實施的安全限制。
換個通俗的比方來說,比如經常會有一些模仿金融機構的釣魚網站,用了和金融機構類似的域名,你點選進去一看,竟然和你熟悉的金融網站一模一樣,如果你沒注意域名的差別,如果你在網站上輸入了卡號和密碼資訊那就很危險了,有可能這個網站是frame了金融機構的網站,如果金融網站沒有做相關的安全限制,你的資訊完全有可能被非法分子獲取。由此可見瀏覽器的同源策略存在是十分有必要的。
我順便在給大家介紹下如何區分是否是同源,所謂的同源是指,域名,協議,埠均為相同。接下來舉幾個示例,方便大家進行理解:
常用方法一:使用 JSONP 進行 Get 請求這應該是我們接觸到的第一個解決跨域的方法,筆者記得前端入門經典紅皮書裡有過介紹,JSONP有兩部分主成:回撥函式和資料。回撥函式是當響應完成在頁面中呼叫的函式,回撥函式的名字一般在請求中進行制定。而資料就是傳入回撥函調函式中的JSON資料。為了解釋這個,還是我們來看下面這個例子吧:
比如我們來實現一個獲取當地天氣資料的功能,我們需要在後端與天氣介面平臺互動獲取天氣資料,前端頁面通過GET後端API的方式獲取天氣資訊。
1、首先定義我們前端頁面的回撥函式功能,我們定義了一個gotWeather的函式:
2、接下來定義請求方法,請注意callback後面的引數和回撥函式保持一致的名字:
3、我們後臺介面最終要返回非類似這樣的資料內容:
你會發現,資料能夠正常返回,你也許會問為什麼這樣可以,不違背同源原則嗎?其實之所以有效,並且不違反安全性,因為這是經過前後端共同協作,約定以這種方式傳遞資料。但是你會發現使用這種方法會有一個問題是,只能用於Get請求。
常用方法二:跨域資源共享(CORS)請求方式目前這種方式用的比較多,應用比較廣泛,如果你的專案受部署環境限制的話,建議還是用這種。
1、什麼是CORS?
CORS是一個W3C標準,全稱是“跨域資源共享”(跨源資源共享)。它允許瀏覽器向跨源伺服器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
CORS需要瀏覽器和伺服器同時支援目前,所有瀏覽器都支援該功能,IE瀏覽器不能低於IE10.IE8 +:IE8 / 9需要使用XDomainRequest物件來支援CORS。
整個CORS通訊過程,都是瀏覽器自動完成,不需要使用者參與。對於開發者來說,CORS通訊與同源的AJAX通訊沒有差別,程式碼完全一樣。瀏覽器一旦發現AJAX請求跨源,就會自動新增一些附加的頭資訊,有時還會多出一次附加的請求,但使用者不會有感覺。因此,實現CORS通訊的關鍵是伺服器。只要伺服器實現了CORS介面,就可以跨源通訊。
CORS 請求分成兩類:簡單請求(simple request)和非簡單請求(not-so-simple request)。
2、什麼是簡單請求?
2.1、首先介紹下什麼是簡單請求,請求方法是以下請求方法:
Head
Get
Post
2.2、HTTP 的頭資訊不超出以下幾種欄位:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不同時滿足上面兩個條件,就屬於非簡單請求。一句話,簡單請求就是簡單的 HTTP 方法與簡單的 HTTP 頭資訊的結合。
2.2、簡單請求的大致流程我做下解釋:
加入我們的一個網站頁面地址需要去請求一個服務端的API,這個頁面的請求頭可能是這樣的:
上面的頭資訊中,Origin欄位用來說明,本次請求來自哪個域(協議 + 域名 + 埠)。伺服器根據這個值,決定是否同意這次請求。
如果Origin指定的源,不在許可範圍內,伺服器會返回一個正常的 HTTP 迴應。瀏覽器發現,這個迴應的頭資訊沒有包含Access-Control-Allow-Origin欄位,就知道出錯了,從而丟擲一個錯誤,被XMLHttpRequest的onerror回撥函式捕獲。注意,這種錯誤無法通過狀態碼識別,因為 HTTP 迴應的狀態碼有可能是200。
如果Origin指定的域名在許可範圍內,伺服器返回的響應,會多出幾個頭資訊欄位。具體的請求互動流程如下圖所示:
如果一切順利正常的話,你就會看到服務端一些返回的頭資訊
3、什麼是非簡單請求
3.1、 簡單的介紹下什麼是非簡單請求(not-so-simple request)
非簡單請求是那種對伺服器提出特殊要求的請求,比如請求方法是PUT或DELETE,或者Content-Type欄位的型別是application/json。
非簡單請求的 CORS 請求,會在正式通訊之前,增加一次 HTTP 查詢請求,稱為“預檢”請求(preflight)。瀏覽器先詢問伺服器,當前網頁所在的域名是否在伺服器的許可名單之中,以及可以使用哪些 HTTP 動詞和頭資訊欄位。只有得到肯定答覆,瀏覽器才會發出正式的XMLHttpRequest請求,否則就報錯。這是為了防止這些新增的請求,對傳統的沒有 CORS 支援的伺服器形成壓力,給伺服器一個提前拒絕的機會,這樣可以防止伺服器大量收到DELETE和PUT請求,這些傳統的表單不可能跨域發出的請求。
3.2、通過示例,我們來了解其實現的原理
3.2.1、比如我們在前端頁面的請求程式碼時這樣的如下所示:
上面程式碼中,HTTP 請求的方法是PUT,並且傳送一個自定義頭資訊X-Custom-Header。
3.2.2、瀏覽器發現,這是一個非簡單請求,就自動發出一個“預檢”請求,要求伺服器確認可以這樣請求。下面是這個“預檢”請求的 HTTP 頭資訊。
“預檢”請求用的請求方法是OPTIONS,表示這個請求是用來詢問的。頭資訊裡面,關鍵欄位是Origin,表示請求來自哪個源。
除了Origin欄位,“預檢”請求的頭資訊包括兩個特殊欄位。
(1)Access-Control-Request-Method 該欄位是必須的,用來列出瀏覽器的 CORS 請求會用到哪些 HTTP 方法,上例是PUT。
(2)Access-Control-Request-Headers 該欄位是一個逗號分隔的字串,指定瀏覽器 CORS 請求會額外發送的頭資訊欄位,上例是X-Custom-Header。
3.3、伺服器收到“預檢”請求以後,檢查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers欄位以後,確認允許跨源請求,就可以做出迴應。
3.4 一旦伺服器通過了“預檢”請求,以後每次瀏覽器正常的 CORS 請求,就都跟簡單請求一樣,會有一個Origin頭資訊欄位。伺服器的迴應,也都會有一個Access-Control-Allow-Origin頭資訊欄位。
3.4 文字內容有點多,把剛才描述的內容用一張流程圖表述下,大家會清晰許多,如下所示:
4、與 JSONP 的比較
CORS 與 JSONP 的使用目的相同,但是比 JSONP 更強大。JSONP 只支援GET請求,CORS 支援所有型別的 HTTP 請求。JSONP 的優勢在於支援老式瀏覽器,以及可以向不支援 CORS 的網站請求資料。
5、接下來給後端開發人員分享下如何配置跨域請求
5.1 PHP 簡單示例
5.2 Node 開發人員使用 Express 簡單示例:
5.2.1 首先安裝 cors 中介軟體:
npm install cors
5.2.3 然後配置比如入口檔案,server/
index.js
5.2.4 你可以對跨域進行配置,如下圖所示:
5.2.5 你可以做個請求示例嘗試下,如果一切正常,你可以在 web 開發者工具中看到如下所示:
java 的由於我不太熟,可以自行解決方案,原理和 PHP 的道理是差不多的。
常用方法三:nginx 反向代理這個方法應用也十分廣泛,也是十分常見的,這也需要服務端配合下面還是用一段Ngxin配置來說明這個問題,如下圖所示:
實現原理類似於Node中介軟體代理,需要你搭建一箇中轉nginx伺服器,用於轉發請求。使用nginx反向代理實現跨域,是最簡單的跨域方式。只需要修改nginx的配置即可解決跨域問題,支援所有瀏覽器,支援session,不需要修改任何程式碼,並且不會影響伺服器效能。實現思路:通過nginx配置一個代理伺服器(域名與domain1相同,埠不同)做跳板機,反向代理訪問domain2介面,並且可以順便修改cookie中domain資訊,方便當前域cookie寫入,實現跨域登入。
小節以上是解決跨域問題最常用的三種方式,應該能解決你業務中遇到的問題,有點需需要提示的是方法二和方法三不要混著用,否則會報“Access-Control-Allow-Origin Not Allow Multiple value”的錯誤,我推薦大家用方法三使用nginx反向代理做跨域解決方案,比較簡單和直接,可謂一勞永逸。當然跨域的方法還有其他的,比如使用WebSocket、postMessage API 、各種 iframe 的解決方案,由於不太常用和篇幅問題原因,就不再一一介紹了,感興趣的小夥伴們可以自行搜尋。
注:本回答第二部部分參考阮一峰的《JavaScript 標準參考教程(alpha)》
-
8 # java架構設計
那麼為什麼有跨域的問題呢?解決跨域問題有哪些方式?搞清楚這兩個問題我們需要了解一下什麼是同源策略。
瀏覽器的同源策略同源策略(Same origin policy)是一種安全約定,是所有主流瀏覽器最核心也是最基本的安全功能之一。同源策略規定:不同域的客戶端指令碼在沒有明確授權的情況下,不能請求對方的資源。同源指的是:域名、協議、埠均相同。
比如我們訪問一個網站
http://www.test.com/index.html,
另外,同源策略又分如下兩種情況:
DOM同源策略:禁止對不同源的頁面DOM進行操作,主要防止iframe的情況。比如iframe標籤裡放一個支付寶付款的頁面,如果沒有同源策略,那麼釣魚網站除了域名不同,其他的則可以和支付寶的網站一模一樣。
XMLHttpRequest同源策略:禁止使用XHR物件向不同源的伺服器發起http請求。比如網站記錄了銀行的cookie,這個時候你訪問了惡意網站,黑客拿到你的cookie,再通過ajax請求之前的銀行網站,便可以輕易的拿到你的銀行資訊。
所以,正是因為有了同源策略,大家的網路環境才相對的安全一些。
跨域問題的解決辦法瞭解了同源策略,就知道為什麼會有跨域問題的產生了,都是為了安全。但是實際研發中,大家還是需要跨域去訪問資源。典型的應用場景就是前後端分離的專案了。那麼我們如何去解決跨域問題呢?
CORS-跨域資源共享CORS是一種W3C標準,定義了當產生跨域問題的時候,客戶端與服務端如何通訊解決跨域問題。實際上就是前後端約定好定義一些自定義的http請求頭,讓客戶端發起請求的時候能夠讓服務端識別出來該請求是過還是不過。
瀏覽器將CORS請求分為簡單請求和非簡單請求:
簡單請求簡單請求必須滿足以下兩個條件:
請求方式必須是HEAD、GET、POST三種方法之一。
Http請求頭必須只能是:Accept、Accept-Lanuage、Content-Lanuage、Last-Event-ID、Content-Type,其中Content-Type只限於三個值 application/x-www-form-urlencoded、multipart/form-data、text/plain。
非簡單請求不滿足簡單請求條件的就是非簡單請求。針對非簡單請求,瀏覽器會發起預檢請求。預檢請求的意思是當瀏覽器檢查到你的頁面含有跨域請求的時候,會發送一個OPTIONS請求給對應的伺服器,以檢測伺服器是否允許當前域名的跨域請求。如果服務端允許該域名請求,則返回204或200狀態碼,瀏覽器接收到允許請求時候再繼續傳送對應的GET/POST/PUT/DELETE請求。同時伺服器端也會告知瀏覽器預檢請求的快取時長是多少,在這個時間範圍內,瀏覽器不會再次發起預檢請求。
原理基本上就是上面說的這些,實際業務中我們如何通過配置來解決跨域問題呢?基本上常見的就是三種方式:
nginx配置通常我們在nginx增加如下配置即可解決跨域問題:
用nginx這種方式是最舒服的,不需要客戶端和服務端多做其他工作,對程式碼無入侵。
jsonp因為script標籤是不受瀏覽器同源策略的影響,允許跨域請求資源(我們的每一個頁面都引用了大量第三方js檔案)。所以可以利用動態建立script標籤,通過src屬性發起跨域請求,這就是jsonp的原理。但是jsonp只支援GET請求,所以並不是一種好的方式。
服務端程式碼控制可以在服務端增加對跨域請求的支援:
這種方式相當於全域性過濾器,對所有請求都過濾一遍。
以上三種方式都可以一定程度上解決跨域問題,但是nginx配置和服務端控制不能同時存在,否則會報“Access-Control-Allow-Origin Not Allow Multiple value”的錯誤。個人比較推薦nginx配置的方式,一勞永逸,不需要每個web專案都去編寫跨域的程式碼。
-
9 # 今早有酒今朝醉
1.首先明白跨域是怎麼導致,跨域是由於瀏覽器的同源策略導致 ,什麼是同源策略,指的不同協議 或者不同域名 或者不同埠 只要是其中一個不同 都會導致跨域問題
2.怎麼解決 只要通過配置請求頭部資訊 放行所有請求域名 以及請求方法
回覆列表
摘要
跨域資源共享(CORS)是前後端分離專案很常見的問題,本文主要介紹當SpringBoot應用整合SpringSecurity以後如何解決該問題。
什麼是跨域問題
CORS全稱Cross-Origin Resource Sharing,意為跨域資源共享。當一個資源去訪問另一個不同域名或者同域名不同埠的資源時,就會發出跨域請求。如果此時另一個資源不允許其進行跨域資源訪問,那麼訪問的那個資源就會遇到跨域問題。
跨域問題演示及解決
我們使用mall專案的原始碼來演示一下跨域問題。此時前端程式碼執行在8090埠上,後端程式碼執行在8080埠上,由於其域名都是localhost,但是前端和後端執行埠不一致,此時前端訪問後端介面時,就會產生跨域問題。
此時發現呼叫登入介面時出現跨域問題。
新增GlobalCorsConfig配置檔案來允許跨域訪問。
package com.macro.mall.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; /** * 全域性跨域配置 * Created by macro on 2019/7/27. */@Configuration public class GlobalCorsConfig { /** * 允許跨域呼叫的過濾器 */ @Bean public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); //允許所有域名進行跨域呼叫 config.addAllowedOrigin("*"); //允許跨越發送cookie config.setAllowCredentials(true); //放行全部原始頭資訊 config.addAllowedHeader("*"); //允許所有請求方法跨域呼叫 config.addAllowedMethod("*"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); }}
發現需要登入認證的/admin/info介面的OPTIONS請求無法通過認證,那是因為複雜的跨越請求需要先進行一次OPTIONS請求進行預檢,我們的應用整合了SpringSecurity,對OPTIONS請求並沒有放開登入認證。
在SecurityConfig類的configure(HttpSecurity httpSecurity)方法中新增如下程式碼。
.antMatchers(HttpMethod.OPTIONS)//跨域請求會先進行一次options請求 .permitAll()
發現已經可以正常訪問。
先發起一次OPTIONS請求進行預檢
請求頭資訊:Access-Control-Request-Headers: content-type Access-Control-Request-Method: POST Origin: http://localhost:8090 Referer: http://localhost:8090/ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
響應頭資訊:Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: content-type Access-Control-Allow-Methods: POST Access-Control-Allow-Origin: http://localhost:8090 Cache-Control: no-cache, no-store, max-age=0, must-revalidate Content-Length: 0 Date: Sat, 27 Jul 2019 13:40:32 GMT Expires: 0 Pragma: no-cache Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers X-Content-Type-Options: nosniff X-Frame-Options: DENY X-XSS-Protection: 1; mode=block
請求成功返回狀態碼為200發起真實的跨域請求
請求頭資訊:Accept: application/json, text/plain, */* Content-Type: application/json;charset=UTF-8 Origin: http://localhost:8090 Referer: http://localhost:8090/ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 {username: "admin", password: "123456"} password: "123456" username: "admin"
響應頭資訊:Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: http://localhost:8090 Cache-Control: no-cache, no-store, max-age=0, must-revalidate Content-Type: application/json;charset=UTF-8 Date: Sat, 27 Jul 2019 13:40:32 GMT Expires: 0 Pragma: no-cache Transfer-Encoding: chunked Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers X-Content-Type-Options: nosniff X-Frame-Options: DENY X-XSS-Protection: 1; mode=block
請求成功返回狀態碼為200