學習ASP.NET Core Blazor編程系列二十七——JWT登錄(2)

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

序言 閑來無聊,前段時間發現一個.net開源框架:masa framework。經過一些小型項目使用,發現確實挺不錯的。然後我又去閱讀了整個masa framework源碼,特此來記錄整個源碼閱讀的過程。 如有錯誤之處還請指點 MASA Framework簡介 ​ Masa Framework是 m ...


學習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) ,我們繼續實現功能。

     5.在Visual Studio 2022的解決方案資源管理器中,滑鼠左鍵選中“Utils”文件夾,右鍵單擊,在彈出菜單中選擇“添加—>新建項”,在彈出對話框中,選擇“介面”,並將介面命名為“IJWTHelper”。如下圖。並添加如下代碼:

using Microsoft.IdentityModel.Tokens;
using System.Security.Claims;
 

namespace BlazorAppDemo.Utils
{

    public interface IJWTHelper

    {

        string CreateJwtToken<T>(T user);

        T GetToken<T>(string Token);

        IEnumerable<Claim> ParseToken(string token);

        string? ValidateJwtToken(IEnumerable<Claim> jwtToken);

        TokenValidationParameters ValidParameters();

    }
}

 

6.在Visual Studio 2022的解決方案資源管理器中,滑鼠左鍵選中“Utils”文件夾,右鍵單擊,在彈出菜單中選擇“添加—>類”,在彈出對話框中,並將類命名為“JWTHelper”。並繼承IJWTHelper介面,添加如下代碼:

 

using BlazorAppDemo.Models;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Security.Claims;
using System.Text;
 
namespace BlazorAppDemo.Utils
{

    public class JWTHelper : IJWTHelper
    {
        private readonly IConfiguration _configuration;
        private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler;

        public JWTHelper(IConfiguration configuration, JwtSecurityTokenHandler jwtSecurityTokenHandler)
        {
            _configuration = configuration;
            _jwtSecurityTokenHandler = jwtSecurityTokenHandler;

        }
        /// <summary>
        /// 創建加密JwtToken
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>

        public string CreateJwtToken<T>(T user)
        {
            var signingAlogorithm = SecurityAlgorithms.HmacSha256;

            var claimList = this.CreateClaimList(user);
            //Signature

            //取出私鑰並以utf8編碼位元組輸出
            var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);
            //使用非對稱演算法對私鑰進行加密
            var signingKey = new SymmetricSecurityKey(secretByte);
            //使用HmacSha256來驗證加密後的私鑰生成數字簽名

            var signingCredentials = new SigningCredentials(signingKey, signingAlogorithm);
            //在 RFC 7519 規範中(Section#4),一共定義了 7 個預設的 Claims。
            //生成Token
            var Token = new JwtSecurityToken(
          issuer: _configuration["Authentication:Issuer"], //發佈者
            audience: _configuration["Authentication:Audience"], //接收者
            claims: claimList, //存放的用戶信息
            notBefore: DateTime.UtcNow, //發佈時間
            expires: DateTime.UtcNow.AddDays(1), //有效期設置為1天
            signingCredentials //數字簽名

            );

            //生成字元串token
            var TokenStr = new JwtSecurityTokenHandler().WriteToken(Token);
            return TokenStr;
        }
 
        public T GetToken<T>(string Token)
        {
            Type t = typeof(T);
 
            object objA = Activator.CreateInstance(t);
            var b = _jwtSecurityTokenHandler.ReadJwtToken(Token);
            foreach (var item in b.Claims)
            {
                PropertyInfo _Property = t.GetProperty(item.Type);
                if (_Property != null && _Property.CanRead)
                {
                    _Property.SetValue(objA, item.Value, null);
                }
 
            }
            return (T)objA;
        }

        /// <summary>
        /// 創建包含用戶信息的CalimList
        /// </summary>
        /// <param name="authUser"></param>
        /// <returns></returns>

        private List<Claim> CreateClaimList<T>(T authUser)
        {

            var Class = typeof(UserInfo);
            List<Claim> claimList = new List<Claim>();

            foreach (var item in Class.GetProperties())
            {

                if (item.Name == "Password")
                {

                    continue;
                }

                claimList.Add(new Claim(ClaimTypes.Name, Convert.ToString(item.GetValue(authUser))));
            }

            return claimList;
        }
    }
}

 

7. 在Visual Studio 2022的解決方案資源管理器中,使用滑鼠左鍵雙擊“Auth”文件夾中的“ImitateAuthStateProvider.cs”文件,在文本編輯器中打開,對代碼進行修改。具體代碼如下:

using BlazorAppDemo.Models;
using BlazorAppDemo.Utils;
using Microsoft.AspNetCore.Components.Authorization;
using System.Security.Claims;


namespace BlazorAppDemo.Auth
{
    public class ImitateAuthStateProvider : AuthenticationStateProvider
    {

        private readonly IJWTHelper jwt;
        public ImitateAuthStateProvider(IJWTHelper _jwt) => jwt = _jwt; //DI

        bool isLogin = false;
        string token = string.Empty;
        public override Task<AuthenticationState> GetAuthenticationStateAsync()
        {

            if (isLogin)
            {
 
                var claims = new List<Claim>()
            {

                new Claim(ClaimTypes.Name,"user"),
                new Claim(ClaimTypes.Role, "admin")
            };

                var anonymous = new ClaimsIdentity(claims, "testAuthType");
                return Task.FromResult(new AuthenticationState(new ClaimsPrincipal(anonymous)));

            }
            else

            {

            var anonymous = new ClaimsIdentity();
 
            return Task.FromResult(new AuthenticationState(new ClaimsPrincipal(anonymous)));
        }

        }
        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());
        }
    }
}

 

8.在Visual Studio 2022的解決方案管理器中,使用滑鼠左鍵,雙擊Program.cs文件,將之在文本編輯器中打開,將我們寫的JWTHelper與JwtSecurityTokenHandler、使用DI方式註入,添加JWT認證服務。具體代碼如下:

using BlazorAppDemo.Data;
using BlazorAppDemo.Models;
using Microsoft.AspNetCore.Components;

using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Components.Authorization;

using BlazorAppDemo.Auth;
using Microsoft.AspNetCore.Authentication.JwtBearer;

using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.IdentityModel.Tokens.Jwt;
using BlazorAppDemo.Utils;

 

var builder = WebApplication.CreateBuilder(args);
 

// Add services to the container.

builder.Services.AddRazorPages();

builder.Services.AddServerSideBlazor();

builder.Services.AddSingleton<WeatherForecastService>();

System.Console.WriteLine(ConfigHelper.Configuration["ConnectionStrings:BookContext"]);
builder.Services.AddDbContextFactory<BookContext>(opt =>
 opt.UseSqlServer(ConfigHelper.Configuration["ConnectionStrings:BookContext"]));

//builder.Services.AddScoped<AuthenticationStateProvider, ImitateAuthStateProvider>();

builder.Services.AddScoped<ImitateAuthStateProvider>();
builder.Services.AddScoped<AuthenticationStateProvider>(implementationFactory =>

implementationFactory.GetRequiredService<ImitateAuthStateProvider>());
builder.Services.AddScoped<JwtSecurityTokenHandler>();
 
//JWT
//JWT認證

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{

    //取出私鑰
    var secretByte = Encoding.UTF8.GetBytes(builder.Configuration["Authentication:SecretKey"]);
    options.TokenValidationParameters = new TokenValidationParameters()

    {
        //驗證發佈者
        ValidateIssuer = true,
        ValidIssuer = builder.Configuration["Authentication:Issuer"],
        //驗證接收者
        ValidateAudience = true,

        ValidAudience = builder.Configuration["Authentication:Audience"],
        //驗證是否過期
        ValidateLifetime = true,
        //驗證私鑰
        IssuerSigningKey = new SymmetricSecurityKey(secretByte)
    };

});
//自己寫的Jwt 擴展
builder.Services.AddScoped<IJWTHelper,JWTHelper>();
 
 
var app = builder.Build();


// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}
 

using (var scope = app.Services.CreateScope())
{

    var services = scope.ServiceProvider;
    try
    {

        Console.WriteLine("資料庫開始初始化。");
        var context = services.GetRequiredService<BookContext>();
        // requires using Microsoft.EntityFrameworkCore;

        context.Database.Migrate();

        // Requires using RazorPagesMovie.Models;
        SeedData.Initialize(services);
        Console.WriteLine("資料庫初始化結束。");
    } 

    catch (Exception ex)

    {
        var logger = services.GetRequiredService<ILogger<Program>>();
        logger.LogError(ex, "資料庫數據初始化錯誤.");

    }
}


app.UseHttpsRedirection();
 
app.UseStaticFiles();

 
app.UseRouting();


app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.UseAuthentication();
app.UseAuthorization();

 

app.Run();

 
9.在Visual Studio 2022的菜單欄上,找到“調試-->開始調試”或是按F5鍵,Visual Studio 2022會生成BlazorAppDemo應用程式,瀏覽器中會Login登錄頁面。

10.我們在用戶名輸入框中輸入用戶名,在密碼輸入框中輸入密碼,點擊“登錄”按鈕,進行模擬登錄。我們進入了系統。並且生成了JWT Token。如下圖。

 

 


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

-Advertisement-
Play Games
更多相關文章
  • 一、標識符 標識符是指定義的具有特殊意義的詞,例如變數、常量、函數名等等,任何一門語言中都對自己的標識符有特殊定義的規則。在 Go 語言中,標識符由字母數字和下劃線組成,並且只能以字母和下劃線開頭,例如: 數字、字母和下劃線組成:123、abc _ 只能以字母和下劃線開頭:abc123、_sysVa ...
  • 靜態類和非靜態類 靜態類只能是內部類,外部類不能用static修飾,內部類可以使用static修飾。 創建方式: 外部類.靜態內部類 對象名=外部類.new 靜態內部類(); 外部類 對象名= new 外部類(); 外部類.非靜態內部類 對象名1 = 對象名.new 非靜態內部類(); 抽象類是否可 ...
  • 1.java開發工具的構成 (1)JVM即java虛擬機,用於解釋翻譯java生成的自解碼文件,因為java中有了這個,才能實現java語言跨平臺運行java自解碼文件 (2)JRE即java運行環境,它是由JVM和java系統類庫構成,JRE是能保證java代碼能夠準確無誤在裝了JRE機器上運行, ...
  • 本文已經收錄到Github倉庫,該倉庫包含電腦基礎、Java基礎、多線程、JVM、資料庫、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分散式、微服務、設計模式、架構、校招社招分享等核心知識點,歡迎star~ Github地址:https://github.c ...
  • 需要使用的 技術 工具: idea 2022 開發工具 MySql 5.6 資料庫工具 Apache Tomcat 8.5.85 web應用部署工具 主要功能有: 用戶登錄 用戶註冊 展示列表信息 涉及到的知識: Servlet JDBC 過濾器 先打開資料庫 創建一個資料庫 然後 創建對應的表結構 ...
  • 可讀、可寫 r+t: 可讀、可寫 w+t: 可寫、可讀 a+t: 可追加、可讀 ## wt with open('36w.txt', 'wt', encoding='utf-8') as fw: print(fw.readable()) print(fw.writable()) False True ...
  • 1.項目 https://github.com/Fody/Costura 2.安裝 Install-Package Costura.Fody -Version 1.6.2 3.反射相關 Assembly.LoadFrom("someLibs.dll").GetType("xxx") 找不到文件 改為 ...
  • 目錄 Fireasy3 揭秘 -- 依賴註入與服務發現 Fireasy3 揭秘 -- 自動服務部署 Fireasy3 揭秘 -- 使用 SourceGeneraor 改進服務發現 Fireasy3 揭秘 -- 使用 SourceGeneraor 實現動態代理(AOP) Fireasy3 揭秘 -- ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...