【SpringBoot教程】SpringBoot 實現前后端分離的跨域訪問(Nginx)

作者簡介:大家好,我是擼代碼的羊駝,前阿里巴巴架構師,現某互聯網公司CTO

聯系v:sulny_ann(17362204968),加我進群,大家一起學習,一起進步,一起對抗互聯網寒冬

# 序言

使用Nginx反向代理,可以解決跨域無權和Session丟失的問題,十分方便。下面我們以前后端分離為案例,展開Nginx的使用教程。

# 配置和啟動Nginx

下載地址

Nginx下載傳送門:http://nginx.org/en/download.html

注意事項:下載之后,記得解壓到全英文路徑,避免中文路徑導致Nginx啟動失敗。

修改配置

打開nginx.conf ,清空配置項,然后將下面的配置信息原封不動拷貝進去:

worker_processes  1;
events {    worker_connections  1024;}
http {    include       mime.types;    default_type  application/octet-stream;
    sendfile        on;    keepalive_timeout  65;
    #前端頁面服務器    server {        #監聽端口和域名        listen       7000;         server_name  localhost;
        #添加頭部信息        proxy_set_header Cookie $http_cookie;        proxy_set_header X-Forwarded-Host $host;        proxy_set_header X-Forwarded-Server $host;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;                #添加攔截路徑和代理地址        location /api/ {                             proxy_pass http://localhost:8080/;  #注意:使用代理地址時末尾記得加上斜杠"/"。              }                #添加攔截路徑和根目錄        location / {               root   html/hehe;  #注意:使用"/"攔截全路徑的時候記得放在最后。               index  index.html index.htm;  #index表示首頁         }                       }}
 

快速啟動

在Windows 環境中:

  • 快速啟動Nginx:右鍵管理員模式,運行nginx.exe。

  • 快速關閉Nginx:在nginx主目錄,添加關閉Nginx的命令。

其中結束Nginx.bat的具體內容如下:

taskkill /f /im nginx.exe
 

使用命令快速關閉Nginx

# 部署前端頁面

前后端分離后,可以直接將靜態資源(例如前端頁面)部署到Nginx的html目錄。這里我們在$nginx_home/html目錄下創建一個名為hehe的文件夾,并添加一個頁面(index.html)用于跨域訪問測試,index頁面內容如下:

???????

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8"/>    <title>Page Index</title></head><body><h2>前臺系統7000</h2><p id="info1"></p><p id="info2"></p></body>
<script src="js/jquery.js"></script><script>        $.ajax({            url: 'http://localhost:7000/api/user/login/verifyCode',            type: "POST",            success: function (data) {                //1.獲取驗證碼                $("#info1").html("跨域訪問成功:verifyCode:" + data);                //2.核對驗證碼                $.ajax({                    url: 'http://localhost:7000/api/user/login/checkVerifyCode',                    type: "POST",                    success: function (data) {                        $("#info2").html("跨域訪問成功:checkVerifyCode:" + data);                    }                });            },            error: function (data) {                $("#info1").html("跨域失敗!!");            }        });</script>
</html>
 

#? 啟動后端系統

首先在POM文件添加Web依賴,然后編寫控制層,提供對外的訪問接口。默認啟動端口是8080.

???????

package com.hehe;
@SpringBootApplication@RestController@RequestMapping("/user/login/*")public class SpringBootNginxApplication {    //在攔截器打印訪問URL    @Bean    public WebMvcConfigurer webMvcConfigurer() {        return new WebMvcConfigurer() {            @Override            public void addInterceptors(InterceptorRegistry registry) {                registry.addInterceptor(new HandlerInterceptor() {                    @Override                    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {                        if(response.getStatus()/100>=4){                            System.err.println("訪問URL:"+request.getAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE));                        }else {                            System.out.println("訪問URL:"+request.getRequestURI());                        }                    }                });            }        };    }    //提供驗證碼    @RequestMapping("verifyCode")    public String verifyCode(HttpServletRequest request) {        request.getSession().setAttribute("verifyCode", "N7GX");        return request.getSession().getId() + ":" + request.getSession().getAttribute("verifyCode");    }
    //核對驗證碼    @RequestMapping("checkVerifyCode")    public String checkVerifyCode(HttpServletRequest request) {        return request.getSession().getId() + ":" + request.getSession().getAttribute("verifyCode");    }
    public static void main(String[] args) {        SpringApplication.run(SpringBootNginxApplication.class, args);    }}
 

# 測試跨域訪問

打開瀏覽器,訪問?http://localhost:7000/api/user/login/verifyCode?,可以看到后臺獲取的Session和第一次生成的驗證碼。如圖:

打開瀏覽器,訪問?http://localhost:7000/api/user/login/checkVerifyCode?,可以看到后臺獲取的Session和第二次取出的驗證碼。

由上圖可以看到,跨域訪問成功,并且Session沒有丟失。

# Nginx跨域總結

Nginx VS ?CORS

簡單來說,Nginx是間接跨域,而CORS則實現了直接跨域。Nginx的反向代理“欺詐了”瀏覽器,所以瀏覽器和服務器都認為是同源訪問,所以Session不會丟失。

(PS:如果發生跨域訪問,服務器會每次都創建新的Session,所以才造成了前后端分離的Session丟失問題。) 至于CORS這種跨域機制的安全性和靈活性更高,但需要自己解決跨域訪問Session丟失的問題,通常情況可以采用Session+Redis來實現Session共享。)

Nginx跨域實現過程:

第1步:http://localhost:7000/index.html


第2步:http://localhost:7000/api/user/login/verifyCode

第1步是打開頁面,第2步是在這個頁面發起AJAX請求,并且請求的域名端口均與當前訪問頁面相同,屬于同源操作,所以瀏覽器不會報出跨域禁止的錯誤。

第3步:http://localhost:8080/user/login/verifyCode

第3步是本案例最為關鍵的一步,真正的跨域操作由Nginx的proxy_pass進行完成,并成功將驗證碼信息以代理的身份返回給瀏覽器,讓瀏覽器處于同源訪問后臺的錯覺。打開F12可以看到代理服務器:

關于proxy_pass 斜杠"/' 的坑

通常情況下,建議大家在代理地址末尾加上"/" ,表示轉發后就是proxy_pass直接拼接映射路徑。

Nginx代理效果:


轉發前URL:http://localhost:7000/api/user/login/verifyCode
轉發后URL:http://localhost:8080/hehe/user/login/verifyCode

???????

     server {        listen       7000;         server_name  localhost;                #正確示范: 末尾加斜杠"/"        location /api/ {                             proxy_pass http://localhost:8080/hehe/;         }                        }
 

如果代理地址末尾沒有加斜杠的話,表示轉發后也是proxy_pass直接拼接映射路徑,但是,拼接的時候會少了個"/",這樣會引發訪問路徑錯誤。

Nginx代理效果:


轉發前URL:http://localhost:7000/api/user/login/verifyCode


轉發后URL:http://localhost:8080/heheuser/login/verifyCode

???????

     server {        listen       7000;         server_name  localhost;                #錯誤示范: 末尾無斜杠        location /api/ {                             proxy_pass http://localhost:8080/hehe;         }                        }
 

為了更方便大家,看到在Nginx調整了proxy_pass有無斜杠的區別,樓主在控制臺打印了每次請求訪問的URL地址,這樣更加清晰:

具體做法:關閉Nginx 將代理地址修改為:proxy_pass

http://localhost:8080/hehe?,然后啟動Nginx,在瀏覽器訪問http://localhost:7000/api/user/login/verifyCode,然后查看控制臺打印的URL信息。清楚的看到了因為少了斜杠而導致拼接成錯誤路徑,如下:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/213198.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/213198.shtml
英文地址,請注明出處:http://en.pswp.cn/news/213198.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mybatis之核心配置文件詳解、默認類型別名、Mybatis獲取參數值的兩種方式

學習的最大理由是想擺脫平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;遲一天就多一天平庸的困擾。各位小伙伴&#xff0c;如果您&#xff1a; 想系統/深入學習某技術知識點… 一個人摸索學習很難堅持&#xff0c;想組團高效學習… 想寫博客但無從下手&#xff0c;急需…

arm-none-eabi-gcc not find

解決辦法&#xff1a;安裝&#xff1a;gcc-arm-none-eabi sudo apt install gcc-arm-none-eabi; 如果上邊解決問題了就不用管了&#xff0c;如果解決不了&#xff0c;加上下面這句試試運氣&#xff1a; $ sudo apt-get install lsb-core看吧方正我是運氣還不錯&#xff0c;感…

leetcode周賽375 - 12 - 10

比賽地址 : 競賽 - 力扣 (LeetCode) t1 : 直接暴力即可 class Solution { public:int countTestedDevices(vector<int>& b) {int n b.size();int ans 0;for(int i0;i<n;i){if(b[i]>0){ans ;for(int ji1;j<n;j){b[j] max(b[j]-1,0);}}}return ans;} };…

SSL 數字證書的一些細節

參考&#xff1a;TLS/SSL 協議詳解(6) SSL 數字證書的一些細節1 證書驗證 地址&#xff1a;https://wonderful.blog.csdn.net/article/details/77867063 參考&#xff1a;TLS/SSL協議詳解 (7) SSL 數字證書的一些細節2 地址&#xff1a;https://wonderful.blog.csdn.net/articl…

Python學習筆記-類

1 定義類 類是函數的集合&#xff0c;class來定義類 pass并沒有實際含義&#xff0c;只是為了代碼能執行通過&#xff0c;不報錯而已&#xff0c;相當于在代碼種占一個位置&#xff0c;后續完善 類是對象的加工廠 2.創建對象 carCar()即是創建對象的過程 3、類的成員 3.1 實例…

福德植保無人機:綠色農業的新篇章

今天&#xff0c;我們榮幸地向您介紹福德植保無人機&#xff0c;一種改變傳統農業種植方式&#xff0c;引領綠色農業的新科技產品。福德植保無人機以其高效、環保、安全的特點&#xff0c;正逐漸成為植保行業的新寵。福德植保無人機是一種搭載了高性能發動機和精確噴灑系統的飛…

代碼隨想錄算法訓練營第四十六天 _ 動態規劃_背包問題總結。

學習目標&#xff1a; 動態規劃五部曲&#xff1a; ① 確定dp[i]的含義 ② 求遞推公式 ③ dp數組如何初始化 ④ 確定遍歷順序 ⑤ 打印遞歸數組 ---- 調試 引用自代碼隨想錄&#xff01; 本文大多數內容引用自代碼隨想錄 60天訓練營打卡計劃&#xff01; 學習內容&#xff1a; …

POJ - 2528 Mayor‘s posters

本題注意離散化的時候可能會出現區間串聯情況&#xff0c;比如 [1,10] [5,10] [1,4] 和 [1,10] [6,10] [1,4] 直接離散化的話兩者一樣&#xff0c;但是實際上是不一樣的 解決辦法是你在相鄰的差不是1的數對中再插一個數就好了 離線區間染色 查詢根節點 #include<iostrea…

ASPICE-汽車軟件開發能力評級

Automotive SPICE&#xff08;簡稱A-SPICE 或 ASPICE&#xff09;&#xff0c;全稱是“Automotive Software Process Improvement and Capacity dEtermination”&#xff0c;即“汽車軟件過程改進及能力評定”模型框架。 常被用于評估一家汽車軟件供應商的軟件開發能力&#x…

數組|73. 矩陣置零 48. 旋轉圖像

73. 矩陣置零 **題目:**給定一個 m x n 的矩陣&#xff0c;如果一個元素為 0 &#xff0c;則將其所在行和列的所有元素都設為 0 。請使用 原地 算法。 題目鏈接&#xff1a;矩陣置零 class Solution {public void setZeroes(int[][] matrix) {Stack<int[]> mapofzerone…

【Python必做100題】之第三題(找出100以內的奇數并打印)

思路&#xff1a; 1、定義一個空列表來存儲所有的奇數 2、判斷是奇數就追加到列表的末尾 3、打印所有的奇數 代碼如下&#xff1a; list [ ] #定義一個列表來存儲所有的奇數 for i in range (1,100):if i % 2 ! 0: #判斷是否為奇數list.append(i) #追加到列表的末尾 prin…

使用draw.io如何讓矩形單個邊框有顏色其余邊框為空白?

方法步驟: 第一步&#xff1a;用戶打開Draw.io軟件&#xff0c;并來到流程圖的編輯頁面上&#xff1b; 第二步&#xff1a;接著在左側的圖形庫中點擊矩形選項&#xff0c;成功將其添加到流程圖的繪制頁面上&#xff1b; 第三步&#xff1a;這時用戶點擊矩形并在右側窗口中點…

C++ //習題2.3 寫出以下程序運行結果。請先閱讀程序,分析應輸出的結果,然后上機驗證。

C程序設計 &#xff08;第三版&#xff09; 譚浩強 習題2.3 習題2.3 寫出以下程序運行結果。請先閱讀程序&#xff0c;分析應輸出的結果&#xff0c;然后上機驗證。 #include <iostream> using namespace std;int main(){char c1 a, c2 b, c3 c, c4 \101, c5 \116…

DL Homework 10

習題6-1P 推導RNN反向傳播算法BPTT. 習題6-2 推導公式(6.40)和公式(6.41)中的梯度 習題6-3 當使用公式(6.50)作為循環神經網絡的狀態更新公式時&#xff0c; 分析其可能存在梯度爆炸的原因并給出解決方法&#xff0e; 當然&#xff0c;因為我數學比較菜&#xff0c;我看了好半…

Vue之數據綁定

在我們Vue當中有兩種數據綁定的方法 1.單向綁定 2.雙向綁定 讓我為大家介紹一下吧&#xff01; 1、單向綁定(v-bind) 數據只能從data流向頁面 舉個例子&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"…

BASH中export使用:命令行中傳入變量

可以看到通過export address/project這句話 定義了一個變量address,數值為/project。

運維06:監控

監控生命周期 1.服務器上架到機柜2.基礎設施監控 服務器溫度&#xff0c;風扇轉速 ipmitool命令&#xff0c;只能用在物理機上 存儲的監控&#xff08;df, fdisk, iotop&#xff09; cpu&#xff08;lscpu, uptime, top, htop, glances&#xff09; 內存情況&#xff08;free&…

MVC Gantt Wrapper:RadiantQ jQuery

The RadiantQ jQuery Gantt Package includes fully functional native MVC Wrappers that let you declaratively and seamlessly configure the Gantt component within your aspx or cshtm pages just like any other MVC extensions. 如果您還沒有準備好轉向完全基于客戶端…

(C++)只出現一次的數字I--異或

個人主頁&#xff1a;Lei寶啊 愿所有美好如期而遇 力扣&#xff08;LeetCode&#xff09;官網 - 全球極客摯愛的技術成長平臺備戰技術面試&#xff1f;力扣提供海量技術面試資源&#xff0c;幫助你高效提升編程技能&#xff0c;輕松拿下世界 IT 名企 Dream Offer。https://le…

OpenAI承認ChatGPT變懶惰,正在修復該問題

OpenAI旗下的官方ChatGPT賬號在社交平臺表示&#xff0c;已經收到了大量用戶關于GPT-4變懶惰的反饋。 這是因為自11月11日以來&#xff0c;OpenAI就沒有更新過該模型。當然這不是故意的&#xff0c;大模型的行為是不可預測的&#xff0c;正在研究修復該問題。 外界猜測&#x…