學習ASP.NET Core Blazor編程系列三十——JWT登錄(4)

来源:https://www.cnblogs.com/chillsrc/archive/2023/03/19/17232979.html
-Advertisement-
Play Games

大家好,我是沙漠盡頭的狼,今天介紹一個WPF開源項目-NodeNetwork,它可以幫助我們快速構建和定製網路拓撲圖。 一、前言 在現代軟體開發中,數據可視化和可交互性越來越受到關註。為了實現這一點,通常需要使用各種圖表、表格、網路拓撲圖等控制項。然而,對於某些特殊的場景,這些控制項可能無法滿足需求,此 ...


學習ASP.NET Core Blazor編程系列文章之目錄 學習ASP.NET Core Blazor編程系列一——綜述 學習ASP.NET Core Blazor編程系列二——第一個Blazor應用程式(上)
學習ASP.NET Core Blazor編程系列三——實體 學習ASP.NET Core Blazor編程系列五——列表頁面 學習ASP.NET Core Blazor編程系列七——新增圖書 學習ASP.NET Core Blazor編程系列八——數據校驗 學習ASP.NET Core Blazor編程系列十三——路由(完) 學習ASP.NET Core Blazor編程系列十五——查詢 學習ASP.NET Core Blazor編程系列十六——排序 學習ASP.NET Core Blazor編程系列二十——文件上傳(完) 學習ASP.NET Core Blazor編程系列二十一——數據刷新  學習ASP.NET Core Blazor編程系列二十二——登錄(1) 學習ASP.NET Core Blazor編程系列二十七——JWT登錄(1)  

十三、實現登出

    至此關於Blazor的內容,先寫到這裡, 我們基本上完成了登入、增加、刪除、查詢、修改等功能,應對一般的應用,已經足夠。今天實現登錄功能。有登入,必然要有登出,本文我們來介紹一下如何登出。

1. 在Visual Studio 2022的解決方案資源管理器中,滑鼠左鍵選中“Pages”文件夾,右鍵單擊,在彈出菜單中選擇“添加—>Razor組件…”,並將組件命名為“Logout.razor”。登出組件的功能是用於退出登入,返迴首面。其代碼如下:

@page "/Logout"
@using BlazorAppDemo.Auth;
@inject IAuthService authService
@inject NavigationManager navigation 

@code {
    protected override async Task OnInitializedAsync()
    {

        await authService.LogoutAsync();
        navigation.NavigateTo("/");
    }

}
2. 在Visual Studio 2022的解決方案管理器中,使用滑鼠左鍵,雙擊TokenManager.cs文件,對代碼進行修改。具體代碼如下:

 

using BlazorAppDemo.Models;
using System.Collections.Concurrent;
 
namespace BlazorAppDemo.Utils
{
 
 
    public class TokenManager
    {
 
        private const string TOKEN = "authToken";
 
        private static readonly ConcurrentDictionary<string, UserToken> tokenManager;
         static TokenManager()
        {
            tokenManager=new ConcurrentDictionary<string, UserToken>();
        }

        public static ConcurrentDictionary<string, UserToken> Instance { get { return tokenManager; } }
 
        public static string Token { get { return TOKEN; } }
 
        public static bool RemoveToken(string token)
        {
            if (tokenManager.TryRemove(token,out UserToken delUserToken))
            {
                Console.WriteLine($"delete token {delUserToken.Token}");
                return true;
            }
            else
            {

                Console.WriteLine($"unable delete token {delUserToken.Token}");
                return false;
            }
        }
    }
}

3.在Visual Studio 2022的解決方案資源管理器中,滑鼠左鍵雙擊“Api”文件夾中的 “AuthController.cs”文件,將此文件中的Logout方法的代碼補全。代碼如下:

using BlazorAppDemo.Models;
using BlazorAppDemo.Utils;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Linq;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
 
namespace BlazorAppDemo.Api
{
    [Route("api/[controller]")]
    [ApiController]
    public class AuthController : ControllerBase
    {
        private readonly IJWTHelper jwtHelper;
       
 
        public AuthController(IJWTHelper _IJWTHelper)
        {
            this.jwtHelper = _IJWTHelper;
           
            }
 
        [HttpPost("Login")]
            public async Task<ActionResult<UserToken>> Login(UserInfo userInfo)
        {
            //Demo用
            if (userInfo.UserName == "admin" && userInfo.Password == "111111")
            {
                return BuildToken(userInfo);
            }
            else
            {
                UserToken userToken = new UserToken()
                {
                    StatusCode = System.Net.HttpStatusCode.Unauthorized,
                    IsSuccess = false
                   
                };
                return userToken;
            }
        }
      
 
        /// <summary>
        /// 建立Token
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        private UserToken BuildToken(UserInfo userInfo)
        {
           
            string jwtToken = jwtHelper.CreateJwtToken<UserInfo>(userInfo);
 
            //建立UserToken,回傳客戶端
            UserToken userToken = new UserToken()
            {
                StatusCode = System.Net.HttpStatusCode.OK,
                Token = jwtToken,
                ExpireTime = DateTime.Now.AddMinutes(30),
                IsSuccess= true
               
            };
            return userToken;
        }

   [HttpGet("Logout")]
        public async Task<ActionResult<UserToken>> Logout()
        {
           bool flag= TokenManager.RemoveToken(TokenManager.Token);
          
            var response = new UserToken();
            response.IsSuccess = !flag;
            return response;
        }
    }
}
 

4.在Visual Studio 2022的解決方案資源管理器中,滑鼠左鍵選中“Auth”文件夾中的 “AuthService.cs”文件,將此文件中的LogoutAsync方法中添加如下代碼:

using BlazorAppDemo.Models;
using BlazorAppDemo.Utils;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Concurrent;
using System.Net.Http;
using System.Text;
 
namespace BlazorAppDemo.Auth
{
 
    public class AuthService : IAuthService
    {
        private readonly HttpClient httpClient;
        private readonly AuthenticationStateProvider authenticationStateProvider;
        private readonly IConfiguration configuration;
        private readonly Api.AuthController authController;
        private readonly string currentUserUrl, loginUrl, logoutUrl;     

        public AuthService( HttpClient httpClient, AuthenticationStateProvider authenticationStateProvider, 
IConfiguration configuration,Api.AuthController authController) {
this.authController = authController; this.httpClient = httpClient; this.authenticationStateProvider = authenticationStateProvider; this.configuration = configuration; currentUserUrl = configuration["AuthUrl:Current"] ?? "Auth/Current/"; loginUrl = configuration["AuthUrl:Login"] ?? "api/Auth/Login"; logoutUrl = configuration["AuthUrl:Logout"] ?? "/api/Auth/Logout/"; } public async Task<UserToken> LoginAsync(UserInfo userInfo) { response.Content.ReadFromJsonAsync<UserToken>(); var result = authController.Login(userInfo); var loginResponse = result.Result.Value; if (loginResponse != null && loginResponse.IsSuccess) { TokenManager.Instance.TryAdd(TokenManager.Token, loginResponse); ((ImitateAuthStateProvider)authenticationStateProvider).NotifyUserAuthentication(loginResponse.Token); httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer",
loginResponse.Token);
return loginResponse; } return new UserToken() { IsSuccess = false }; } public async Task<UserToken> LogoutAsync() { var result = authController.Logout(); var logoutResponse = result.Result.Value; ((ImitateAuthStateProvider)authenticationStateProvider).NotifyUserLogOut(); httpClient.DefaultRequestHeaders.Authorization = null; return logoutResponse; } } }

 

LogoutAsync方法:
  • 將token從TokenManger實例中移除
  • 通知前面頁面更新登錄狀態
  • 將request中的header參數bearer token移除。

 

5. 在Visual Studio 2022的解決方案管理器中,使用滑鼠左鍵,雙擊ImitateAuthStateProvider.cs文件,對代碼進行修改。具體代碼如下:

using BlazorAppDemo.Models;
using BlazorAppDemo.Utils;
using Microsoft.AspNetCore.Components.Authorization;
using System.Net.Http;
using System.Security.Claims;
 
namespace BlazorAppDemo.Auth
{
    public class ImitateAuthStateProvider : AuthenticationStateProvider
    {
        private readonly IJWTHelper jwt;
        private AuthenticationState anonymous;
        private readonly HttpClient httpClient;
 
        public ImitateAuthStateProvider(IJWTHelper _jwt, HttpClient httpClient)
        {
            anonymous = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
            jwt = _jwt;
            this.httpClient = httpClient;
        }
 
        bool isLogin = false;
        string token = string.Empty;
        public override Task<AuthenticationState> GetAuthenticationStateAsync()
        {
            //確認是否已經登錄
            UserToken userToken;
                TokenManager.Instance.TryGetValue(TokenManager.Token,out userToken);
            string tokenInLocalStorage=string.Empty;
            if (userToken != null)
            {
                tokenInLocalStorage = userToken.Token;
            }

            if (string.IsNullOrEmpty(tokenInLocalStorage))
            {
                //沒有登錄,則返回匿名登錄者
                return Task.FromResult(anonymous);
            }
 
            //將token取出轉換為claim
            var claims = jwt.ParseToken(tokenInLocalStorage);
 
            //在每次request的header中都將加入bearer token
            httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", 
tokenInLocalStorage);
//回傳帶有user claim的AuthenticationState return Task.FromResult(new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims, "jwt")))); } public void Login(UserInfo request) { //1.驗證用戶賬號密碼是否正確 if (request == null) { isLogin=false; } if (request.UserName == "user" && request.Password == "111111") { isLogin = true; token= jwt.CreateJwtToken<UserInfo>(request); Console.WriteLine($"JWT Token={token}"); } NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); } public void NotifyUserAuthentication(string token) { var claims = jwt.ParseToken(token); var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(claims, "jwt")); var authState = Task.FromResult(new AuthenticationState(authenticatedUser)); NotifyAuthenticationStateChanged(authState); } public void NotifyUserLogOut() { var authState = Task.FromResult(anonymous); NotifyAuthenticationStateChanged(authState); } } }

 

6. 在Visual Studio 2022的解決方案管理器中,使用滑鼠左鍵,雙擊MainLayout.razor文件,對代碼進行修改。具體代碼如下:

 

@using BlazorAppDemo.Pages
@inherits LayoutComponentBase
 
<PageTitle>BlazorAppDemo</PageTitle>
 
<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>
 
    <main>
        <AuthorizeView>
            <Authorized>
              <div class="top-row px-4">


            <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
                <div class ="col-3 oi-align-right">
                        你好, @context.User.Identity.Name!<a href="/Logout">Logout</a>
                        </div>
      </div>     
 
        <article class="content px-4">
                    @Body
        </article>

            </Authorized>
            <NotAuthorized>
                <div style="margin: 120px 0; width:100%; text-align: center; color: red;">

                    <span style="font-size:20px">檢測到登錄超時,請重新<a href="/login" style="text-decoration:underline">登錄</a>

</span> </div> <RedirectToLogin></RedirectToLogin> </NotAuthorized> </AuthorizeView> </main> </div>

7. 在Visual Studio 2022的菜單欄上,找到“調試-->開始調試”或是按F5鍵,Visual Studio 2022會生成BlazorAppDemo應用程式。瀏覽器會打開登錄頁面。我們在登錄頁面的用戶名輸入框中輸入用戶名,在密碼輸入框中輸入密碼,點擊“登錄”按鈕,進行登錄。我們進入了系統,在頁面的右上角處,會出現登錄用戶的用戶名,與一個“Logout”按鈕。如下圖。

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 發現報錯:RuntimeError: NCCL error in: /pytorch/torch/lib/c10d/ProcessGroupNCCL.cpp:784, unhandled system error想在linux上跑跑mmclassification中的resnet網路,但是報錯,查閱... ...
  • Pandas庫專為數據分析而設計,它是使Python成為強大而高效的數據分析環境的重要因素。 一、Pandas數據結構 1、import pandas as pd import numpy as np import matplotlib.pyplot as plt 2、S1=pd.Series([‘ ...
  • 本文主要介紹 Tomcat Native Library 安裝及使用,文中所使用到的軟體版本:Centos 7.9.2009、Java 1.8.0_321、Tomcat 8.5.84、APR 1.7.0。 1、APR 1.1、APR 簡介 APR(Apache Portable Runtime) 是 ...
  • 操作系統 :CentOS 7.6.1810_x64 Python 版本 : 3.9.12 一、背景描述 使用python開發過程中,會遇到需要使用緩存加速應用的情況,比如下麵這些場景: 數據轉換加速 字元串時間轉換成int時間戳; 字元串時間轉換成datetime類型; ... 數據解析加速 byt ...
  • 上一節給大家從源碼級別分析了SNetClient網路客戶端的實現過程,詳見​C++/Qt網路通訊模塊設計與實現(二),並給大家留了一個疑問,即引入SNetClientRunning類是為瞭解決什麼問題? 我們從SNetClient的設計出發,即要求線上程里進行數據包的收發,連接,斷開處理等,這些處理 ...
  • 本文已經收錄到Github倉庫,該倉庫包含電腦基礎、Java基礎、多線程、JVM、資料庫、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分散式、微服務、設計模式、架構、校招社招分享等核心知識點,歡迎star~ Github地址:https://github.c ...
  • 大家好,我是沙漠盡頭的狼。 一. 問題描述 如下圖,定義兩個子類Student和Employ,都繼承自抽象類PersonBase: public abstract class PersonBase { public string Name { get; set; } protected Person ...
  • 前言 年初.NET工程師的求職者反饋不好找工作,尤其是B/S開發,C/S開發稍微好點。這種情況下有好多小伙伴都想轉行了,於是瞭解了一下JAVA,比.NET還捲,還是走.NET內部轉行吧,轉C/S桌面開發。本文介紹.NET幾種桌面開發技術的方向,大家可以參考一下,具體如下。 一、簡介 WinForms ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...