學習ASP.NET Core(11)-解決跨域問題與程式部署
阿新 • • 發佈:2020-06-18
上一篇我們介紹了系統日誌與測試相關的內容並添加了相關的功能;本章我們將介紹跨域與程式部署相關的內容
## 一、跨域
### 1、跨域的概念
1、什麼是跨域?
一個請求的URL由協議,域名,埠號組成,以百度的https://www.baidu.com為例,協議為https,域名由子域名www和主域名baidu組成,埠號若為80會自動隱藏(也可以配置為其它埠,通過代理伺服器將80埠請求轉發給實際的埠號)。而當請求的URL的協議,域名,埠號任意一個於當前頁面的URL不同即為跨域
2、什麼是同源策略?
瀏覽器存在一個同源策略,即為了防範跨站指令碼的攻擊,出現跨域請求時**瀏覽器會限制自身**不能執行其它網站的指令碼(如JavaScript)。所以說當我們把專案部署到Web伺服器後,通過瀏覽器進行請求時就會出現同源策略問題;而像PostMan軟體因其是客戶端形式的,所以不存在此類問題
3、跨域會導致什麼問題?
同源策略會限制以下行為:
- Cookie、LocalStorage和IndexDb的讀取
- DOM和JS物件的獲取
- Ajax請求的傳送
### 2、常用的解決方法
這裡我們將簡單介紹針對跨域問題常用的幾種解決辦法,並就其中的Cors方法進行配置,若對其它方式感興趣,可參照老張的哲學的文章,[⅖ 種方法實現完美跨域](https://www.cnblogs.com/laozhang-is-phi/p/9767400.html#autoid-2-5-0 "點選檢視")
#### 2.1、JsonP
1、原理
上面有提到瀏覽器基於其同源策略會限制部分行為,但對於Script標籤是沒有限制的,而JsonP就是基於這一點,它會在頁面種動態的插入Script標籤,其Src屬性對應的就是api介面的地址,前端會以Get方式將處理函式以回撥的形式傳遞給後端,後端響應後會再以回撥的方式傳遞給前端,最終頁面得以顯示
2、優缺點
JsonP出現時間較早,所以對舊版本瀏覽器支援性較好;但自身只支援Get請求,無法確認請求是否成功
#### 2.2、 CORS
1、原理
CORS的全稱是Corss Origin Resource Sharing,即跨域資源共享,它允許將當前域下的資源被其它域的指令碼請求訪問。其實現原理就是在響應的head中新增Access-Control-Allow-Origin,只要有該欄位就支援跨域請求
2、優缺點
Cors支援所有Http方法,不用考慮介面規則,使用簡單;但是對一些舊版本的瀏覽器支援性欠佳
3、使用
其使用非常簡單,以我們的專案為例,在BlogSystem.Core專案的Startup類的ConfigureServices方法中進行如下配置
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618203743331-614013993.png)
同時需要開啟使用中介軟體,如下:
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618203751912-2104780606.png)
#### 2.3、Nginx
1、原理
跨域問題是指在一個地址中發起另一個地址的請求,而Nginx可以利用其反向代理的功能,接受請求後直接請求該地址,類似打開了一個新的頁面,所以可以避開跨域的問題
2、優缺點
配置簡單,可以降低開發成本,方便配置負載均衡;靈活性差,每個環境都需要進行不同的配置
## 二、程式部署
### 1、部署模式
在.NET Core中,有兩種部署模式,分別為FDD(Framework-dependent)框架依賴釋出模式和SCD(Self-contained)自包含獨立釋出模式
- FDD:此類部署需要伺服器安裝.NET Core SDK環境,部署的包容量會比較小,但可能因SDK版本存在相容性問題;
- SCD:此類部署自包含.NET Core SDK的環境,不同.NET Core版本可以共存,其部署包容量會較大,且需要對伺服器進行相關配置
### 2、常用部署方式
以下內容均參考老張的哲學的文章[最全的部署方案 & 最豐富的錯誤分析](https://www.cnblogs.com/laozhang-is-phi/p/beautifulPublish-mostBugs.html#autoid-2-4-0 "點選檢視"),有興趣的朋友可以參考原文
#### 2.1、Windows平臺
- **直接執行:**釋出目標選擇windows時會在資料夾中生成一個exe檔案,我們可以直接執行exe檔案或使用CLI命令呼叫dll執行;這種方式雖然方便,卻存在一些弊端,比如說部署多個的情況下會存在很多控制檯視窗,如誤操作會導致視窗關閉等;
- **部署服務:**除了上述直接執行的方式外,我們還可以將程式釋出為服務,釋出後我們可以像控制系統服務一樣控制程式的啟動和關閉
需要注意的是上述兩類方法都需要藉助IIS或者是代理伺服器進行服務的轉發,否則只能在本地進行訪問;
#### 2.2、Linux平臺
Linux平臺常用的部署方式即為程式+代理伺服器,但是當我們配置完成後執行程式時,該執行命令會一直佔用操作視窗,所以我們需要使用“守護程序”來解決這個問題,簡單來說就是將程式放到後臺執行,不影響我們進行其他操作
綜上,部署模式、部署方式及部署平臺有多種組合方式,接下來我們挑選下述3種方法進行演示:
| 方案 | 依賴執行時/宿主機 | 依賴代理伺服器 | 其它配置 |
| :--------------------- | :---------------: | :------------: | :--------: |
| Windows程式(SCD)+Nginx | 否 | 是 | 無 |
| Windows服務(FDD)+IIS | 是 | 否 | 設定為服務 |
| Linux程式(FDD)+Nginx | 是 | 是 | 守護程序 |
### 3、程式釋出
1、這裡我們右擊BlogSystem.Core專案,選擇釋出,選擇資料夾後,點選高階
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618203805471-2112300938.png)
2、為了演示後面的釋出例項,這裡我們分別選擇3種組合模式,①獨立+win-x64;②框架依賴+win-x64;③框架依賴+linux-x64
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618203815571-2122595003.png)
3、將釋出例項拷貝到單獨的資料夾種,這裡我們使用SCD-Window驗證下程式能否直接執行,執行BlogSystem.Core.exe,報錯:
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618203826667-1648131458.png)
原來還是老問題,BLL沒有新增到釋出檔案中,我們到專案的bin資料夾下將BLL和DAL的dll檔案分別拷貝至3個資料夾,再次執行,出現**404錯誤**,經過確認發現,首頁對應的是Swagger文件頁面,而在配置中介軟體時我們有新增**開發環境才配置swagger的邏輯**,所以這裡我們可以根據個人需求決定是否新增。
這裡我為了方便確認釋出是否成功,所以將其從判斷邏輯中取出了。重新生成釋出檔案,拷貝BLL和DAL的dll檔案,再次執行,還是報錯。原來時Swagger的XML檔案缺失,從bin資料夾下拷貝新增至釋出檔案,執行後成功顯示頁面
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618203857696-195867446.png)
4、有的朋友會說了,每次都要拷貝這兩個dll和這兩個xml檔案,太麻煩了。其實也是有對應的解決辦法的,我們可以使用dotnet的CLI命令進行釋出,選擇引用的釋出資料夾為bin資料夾,拷貝至釋出資料夾即可,有興趣的朋友可以自行研究
## 三、伺服器釋出
這裡我用的是阿里雲伺服器,Window系統版本是Window Server2012 R2,Linux系統版本是CentOS 8.0;在操作前記得確認拷貝的釋出檔案能否在本地正常執行
### 1、Windows程式(SCD)+Nginx
1、解壓後雙擊exe檔案網站可以正常執行,如下:
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618203909234-1052030594.png)
2、這個時候我們發現了一個問題,伺服器上沒有資料庫,所以無法確認功能是否正常,這裡我們先下載安裝一個Microsoft SQL Server 2012 Express資料庫(建專案時沒有考慮到釋出後測試的問題,實際上像SQLite資料庫是非常符合這類場景的)
安裝完成後我們新建一個BlogSystem的資料庫,通過Sql檔案的形式將資料庫結構和資料匯入至伺服器資料庫,這時候又發現一個問題,由於我們連線資料庫的邏輯放置在model層的BlogSystemContext資料夾下,所以需要將連線中的DataSource更改為Express資料庫,重新發布後覆蓋舊的釋出檔案(系統設計有缺陷,可以將EF上下文檔案放在應用程式層或單獨一層),再次執行,成功執行查詢,如下:
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618203918618-933611089.png)
3、這個時候本地已經可以進行正常的訪問了,但是外部網路是無法訪問呼叫介面的,這裡我們藉助Nginx進行服務的轉發。下載Nginx後解壓對conf資料夾下的nginx.conf檔案進行如下配置:
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618203929101-1681917674.png)
4、在nginx.exe檔案所在目錄的檔案路徑輸入cmd,鍵入nginx啟動服務訪問8081埠,成功顯示頁面(確保core程式正常執行)如下:
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618203937074-715456290.png)
5、這個時候我們使用其它電腦訪問介面,發現還是無法訪問,經過查詢是阿里雲伺服器進行了相關的限制,在阿里雲控制檯配置安全組規則後即可正常訪問,如下:
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618203949288-577347303.png)
6、配置完成後執行,成功訪問該網站且功能正常。這類方法不需要藉助Core的執行時環境,可以說十分便捷
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618203957865-1309850835.png)
### 2、Windows服務(FDD)+IIS
1、首先我們將FDD釋出檔案壓縮後拷貝至Window Server主機,因FDD的部署方法需要藉助.NET Core執行時環境,所以這裡我們首先到官網https://dotnet.microsoft.com/download/dotnet-core/current/runtime下載安裝.NET Core執行時,這裡我們選擇的是右邊這個,安裝完需要重新啟動
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618204008107-836350481.png)
2、上一個方法中桌面顯示控制檯視窗顯然不是一個較佳的方案,所以這裡我們將其註冊為服務。官方提供了ASP.NET Core服務託管的方法,但使用較為複雜,這裡我們藉助一個名為nssm的工具來達到同樣的目的。我們下載nssm後,在其exe路徑執行cmd命令,執行nssm install,在彈出的視窗中進行如下配置:
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618204017289-799062553.png)
3、我們在系統服務中開啟BlogSytem.Core_Server,在控制面版中選擇安裝IIS服務,併發布對應的專案,安裝完成後,新增部署為8082埠,將應用程式池修改為無託管,如下:
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618204025498-751734524.png)
4、執行網站,成功顯示頁面,但是進行功能試用時發現報錯;經過確認是由於IIS應用程式池的使用者驗證模式和sqlserver的驗證模式不同,解決辦法有三種①修改應用程式池高階設定中的程序模型中的標識②將連線資料庫字串中的Integrated Security=True去除,並新增資料庫連線對應的賬號密碼③在資料庫的“安全性”>“登入名”裡面,新增對應IIS程式池的名稱,並在這個使用者的“伺服器角色”和“使用者對映”中給他對應的許可權
後續嘗試方案一失敗,嘗試方案二成功,方案三由於要安裝SSMS所以沒有嘗試,有遇到相同問題的朋友可以自己試下
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618204035697-1883882797.png)
### 3、Linux程式(FDD)+Nginx
1、首先我們使用MobaXterm工具登入至Linux主機(選擇此工具是由於其)同時支援檔案傳送和命令列操作),這裡使用的Linux版本是CentOS 8.0;藉助MobaXterm工具在home資料夾下建立WebSite資料夾,並在其內部建立BlogSystem資料夾,將我們準備好的FDD部署方式的釋出檔案上傳至此資料夾後,使用命令`sudo dnf install dotnet-sdk-3.1`安裝.net core sdk,如下圖
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618204045341-380524794.png)
2、輸入`cd /home/WebSite/BlogSystem`切換至專案資料夾後,使用`dotnet BlogSystem.Core.dll`執行程式,成功執行,但是由於我們沒有資料庫,且未配置代理伺服器,所以無法驗證服務是否正常執行;所以這裡我們先參照微軟doc[快速入門:在 Red Hat 上安裝 SQL Server 並建立資料庫](https://docs.microsoft.com/zh-cn/dotnet/core/deploying/ "點選檢視")安裝Sql Server資料庫(阿里雲預設安裝了python3作為直譯器所以無需重複安裝),安裝完成後我們開放在阿里雲實例中開放1433埠,使用視覺化工具匯入表結構和資料
3、完成上述操作後我們需要配置守護程序,將程式放在後臺執行。首先我們在/etc/systemd/system下新建守護程序檔案,檔名以.service結尾,這裡我們新建名為BlogSystem.service檔案,使用MobaXterm自帶的編輯器開啟檔案後進行如下配置,**注意後面的中文備註需要去除否則會報錯**
```
[Unit]
Description=BlogSystem #服務描述,隨便填就好
[Service]
WorkingDirectory=/home/WebSite/BlogSystem/ #工作目錄,填你應用的絕對路徑
ExecStart=/usr/bin/dotnet /home/WebSite/BlogSystem/BlogSystem.Core.dll #啟動:前半截是你dotnet的位置(一般都在這個位置),後半部分是你程式入口的dll,中間用空格隔開
Restart=always
RestartSec=25 #如果服務出現問題會在25秒後重啟,數值可自己設定
SyslogIdentifier=BlogSystem #設定日誌標識,此行可以沒有
User=root #配置服務使用者,越高越好
Environment=ASPNETCORE_ENVIRONMENT=Production
[Install]
WantedBy=multi-user.target
```
我們使用`cd /etc/systemd/system/`切換至BlogSystem.service對應的目錄,使用`systemctl enable BlogSystem.service`設定為開機執行後,再使用`systemctl start BlogSystem.service`啟動服務,另外可以使用`systemctl status BlogSystem`確認服務狀態
4、接下來我們安裝代理Nginx代理預設的5000埠,使用`sudo yum install nginx`安裝nginx後,我們到\etc\nginx資料夾下開啟nginx.conf檔案進行如下配置:
![](https://img2020.cnblogs.com/blog/2019059/202006/2019059-20200618204101687-1678312323.png)
配置完成我們進入\etc\nginx資料夾下,使用`systemctl enable nginx`將nginx設定為開機啟動,並使用`systemctl start nginx`啟用服務,同樣可以使用`systemctl status nginx`確認其狀態。確認無誤後在阿里雲中開放8081埠,外網可正常訪問,但功能試用時報錯,原來是資料庫連線錯誤,重新設定後即可正常訪問
### 本章完~
---
**本人知識點有限,若文中有錯誤的地方請及時指正,方便大家更好的學習和交流。**
**本文部分內容參考了網路上的視訊內容和文章,僅為學習和交流,地址如下:**
老張的哲學,[系列一、ASP.NET Core 學習視訊教程](https://www.bilibili.com/video/BV1D4411c7s8?p=12 "點選檢視")
solenovex,[ASP.NET Core 3.x 入門視訊](https://www.bilibili.com/video/BV1c441167KQ?p=18"點選檢視")
###