学习ASP.NET Core Blazor编程系列二十七——JWT登录(2)

  • 学习ASP.NET Core Blazor编程系列二十七——JWT登录(2)已关闭评论
  • 318 次浏览
  • A+
所属分类:.NET技术
摘要

     5.在Visual Studio 2022的解决方案资源管理器中,鼠标左键选中“Utils”文件夹,右键单击,在弹出菜单中选择“添加—>新建项”,在弹出对话框中,选择“接口”,并将接口命名为“IJWTHelper”。如下图。并添加如下代码:

 

     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。如下图。

学习ASP.NET Core Blazor编程系列二十七——JWT登录(2)