昨天做的驗證只針對 Identity 系統,沒有包含到我們的日誌,如果在未登入狀態下於網址列輸入 https://localhost:5018/Blog,還是可以看到部落格,讓我們整合驗證。
首先在 Blog.razor 外層加上 <AuthorizeView>,表示包在其中的內容呈現與否的條件為使用者是否獲得驗證,接著在 Blog 內容外加上 <Authorized>,顧名思義就是通過驗證才能看到內容,另外新增一段未通過驗證的 <NotAuthorized> 程式碼。這邊要記得加上 Context="IdentityContext",否則會跟 Blog 的 <EditForm> 本身的 context 產生衝突。

再去 App.razor 用 <CascadingAuthenticationState> 將原本的 <Router> 包裹,告訴 Blazor 所有 Component 都必須經過驗證。

然後是 NavMenu.razor,<Authorized> Component 加上登出連結,登入連結則移到 <NotAuthorized>,圖示也改一下。

這時候要重新啟動系統,驗證機制才會生效,可以看到確實擋住了未驗證存取。

在登入前,先打開 Dev Tool 的 Application 頁籤去看 Cookies,目前只有一個 Cookie。

登入後看到新的 Cookie,這就是我們的 Authentication Cookie。

接著來試試看登出,點擊左邊的 Logout,並沒有如預想中登出,而是來到一個 Log out 頁面,右上角還是登入狀態,Authentication Cookie 也還在。

我們去看 Logout.cshtml.cs,裡面有 OnGet()(站長註:.NET 6 Blazor server 中沒有該方法,請對比)跟 OnPost() 分別對應 HttpGet 及 HttpPost,我們從連結點過來的做法是 HttpGet,但 OnGet() 這裡什麼事都沒做,OnPost() 則呼叫 ASP.NET Core Identity API 將使用者登出。
原文原圖:多了一個 OnGet() 方法

站長 .NET 6 專案截圖:和上面對比,少了一個 OnGet() 方法

Logout.cshtml 也找到了一個 <form> 元素,asp-page 這些 asp- 開頭的程式碼是 ASP.NET Core 的 Tag Helper(標籤協助程式碼),類似 Angular 的 *ngFor,這邊先略過不提,我們看到這裡用了 method="post",還有個 <button type="submit">,對應了剛才的 OnPost()。

通常不會有使用者點了登出後還要再點一次登出,所以我們這邊改動一下,先給 <form> 加上 id="LogoutFormInLogout",再加上一段 <script>,這裡用到 IIFE(Immediately Invoked Functions Expressions),意即不需要呼叫就會執行的函式,一旦使用者進入這頁面就會將 <form> 提交,如此一來,只要點擊 NavMenu 左邊的 Logout 連結,就可以順利登出了。

如果不想要加上 id="LogoutFormInLogout" 這麼長的 id,也可以用 id="logoutForm" 就好,根目錄下的 Pages/Shared/_LoginPartial.cshtml 裡面有個登出的 <form> 已經定義了 id="logoutForm" 這個 id。

不過現在登出後還停留在 Log out 頁面似乎沒有意義,所以將 OnPost() 的 else 區塊改成 return LocalRedirect("~/Blog");,這樣登出後就會回到未驗證的 Blog 頁面。


這樣一來就完成了單一專案的登入驗證機制,而且各種功能、頁面一應俱全,如果只是小型專案的話可以這麼做,明天就來說明這些 ASP.NET Core 的驗證原理。
引用:
註:本文程式碼透過 .NET 6 + Visual Studio 2022 重構,可點選原文連結與重構後程式碼比較學習,謝謝閱讀,支援原作者