六、.Net Core Web Api连接MongoDB添加ASP.NET Core Identity身份验证授权 - 自动创建管理员用户和基础用户

7 篇文章 0 订阅
7 篇文章 0 订阅

六、.Net Core Web Api连接MongoDB添加ASP.NET Core Identity身份验证授权 - 自动创建管理员用户和基础用户

  1. 在VSCode安装包,搜索AspNetCore.Identity.Mongo,安装最新版本即可;
    安装AspNetCore.Identity.Mongo

  2. 更新你的appsettings.Development.json,添加Users和Roles这两个Collection名称的值;

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "TeachingAppDatabase": {
        "BooksCollectionName": "books",
        "UsersCollectionName": "users",
        "RolesCollectionName": "roles",
        "ConnectionString": "Fill it with your MongoDB connection string",
        "DatabaseName": "teaching-blazor-app"
      },
      "AllowedHosts": "*"
    }
    
    
  3. 更新配置类TeachingAppDatabaseSettings.cs,负责读取配置文件中的users和roles collections名称;

    using System;
    namespace TeachingWebApi.Config
    {
    	public class TeachingAppDatabaseSettings
    	{
    		public string BooksCollectionName { get; init; }
    		public string UsersCollectionName { get; init; }
    		public string RolesCollectionName { get; init; }
    		public string ConnectionString { get; init; }
    		public string DatabaseName { get; init; }
    	}
    }
    
  4. 添加模型类TeachingUsers.cs和TeachingRoles.cs,控制Identity用户和角色;

    using System.ComponentModel.DataAnnotations.Schema;
    using AspNetCore.Identity.Mongo.Model;
    
    namespace TeachingWebApi.Models.Identity
    {
        public class TeachingBlazorUser : MongoUser
        {
    
            public string FirstName { get; set; }
    
            public string LastName { get; set; }
    
            public string CreatedBy { get; set; }
    
            [Column(TypeName = "text")]
            public string ProfilePictureDataUrl { get; set; }
    
            public DateTime CreatedOn { get; set; }
    
            public string LastModifiedBy { get; set; }
    
            public DateTime? LastModifiedOn { get; set; }
    
            public bool IsDeleted { get; set; }
    
            public DateTime? DeletedOn { get; set; }
    
            public bool IsActive { get; set; }
    
            public string RefreshToken { get; set; }
    
            public DateTime RefreshTokenExpiryTime { get; set; }
        }
    }
    
    
    using System;
    using System.ComponentModel.DataAnnotations;
    using AspNetCore.Identity.Mongo.Model;
    using MongoDB.Bson;
    
    namespace TeachingWebApi.Models.Identity
    {
        public class TeachingBlazorRole : MongoRole
        {
            public override ObjectId Id { get; set; }
    
            public string Description { get; set; }
    
            public string CreatedBy { get; set; }
    
            public DateTime CreatedOn { get; set; }
    
            public string LastModifiedBy { get; set; }
    
            public DateTime? LastModifiedOn { get; set; }
            
            public TeachingBlazorRole(string roleName, string roleDescription) : base(roleName)
            {
                Description = roleDescription;
            }
        }
    }
    
  5. 在Program.cs添加红色背景的代码,配置MongoDB Identity;

    using AspNetCore.Identity.Mongo;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using MongoDB.Driver;
    using TeachingWebApi.Config;
    using TeachingWebApi.Data.Seeder;
    using TeachingWebApi.Models.Identity;
    using TeachingWebApi.Services;
    using TeachingWebApi.Utils.Data;
    using TeachingWebApi.Utils.Extensions;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();
    builder.Services.AddControllers();
    
    builder.Services.Configure<TeachingAppDatabaseSettings>(
        builder.Configuration.GetSection("TeachingAppDatabase"));
    
    var MongoDbConnectionString = builder.Configuration.GetSection("TeachingAppDatabase").Get<TeachingAppDatabaseSettings>().ConnectionString;
    var MongoDbUsersCollection = builder.Configuration.GetSection("TeachingAppDatabase").Get<TeachingAppDatabaseSettings>().UsersCollectionName;
    var MongoDbRolesCollection = builder.Configuration.GetSection("TeachingAppDatabase").Get<TeachingAppDatabaseSettings>().RolesCollectionName;
    
    builder.Services.AddSingleton<BooksService>();
    
    // MongoDB with Identity
    builder.Services.AddIdentityMongoDbProvider<TeachingBlazorUser, TeachingBlazorRole>(identity =>
                {
                    // Password settings.
                    identity.Password.RequireDigit = false;
                    identity.Password.RequireLowercase = false;
                    identity.Password.RequireNonAlphanumeric = false;
                    identity.Password.RequireUppercase = false;
                    identity.Password.RequiredLength = 1;
                    identity.Password.RequiredUniqueChars = 0;
    
                    // Lockout settings.
                    identity.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
                    identity.Lockout.MaxFailedAccessAttempts = 5;
                    identity.Lockout.AllowedForNewUsers = true;
    
                    // User settings.
                    identity.User.AllowedUserNameCharacters =
                    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
                    identity.User.RequireUniqueEmail = false;
                },
                    mongo =>
                    {
                        mongo.ConnectionString = MongoDbConnectionString;
                        mongo.UsersCollection = MongoDbUsersCollection;
                        mongo.RolesCollection = MongoDbRolesCollection;
                    }
                )
                .AddEntityFrameworkStores<MongoIdentityDbContext>()
                .AddDefaultTokenProviders();
    
    builder.Services.AddTransient<MongoDbContext>();
    builder.Services.AddTransient<MongoIdentityDbContext>();
    
    builder.Services
        .AddTransient<DatabaseSeeder>()
            .AddDbContext<MongoIdentityDbContext>(options => options
                .UseMongoDB(new MongoClient(MongoDbConnectionString), "teaching_blazor_app"));
    
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI();
    }
    app.Initialize(builder.Configuration);
    app.UseHttpsRedirection();
    
    var summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };
    
    app.MapGet("/weatherforecast", () =>
    {
        var forecast = Enumerable.Range(1, 5).Select(index =>
            new WeatherForecast
            (
                DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                Random.Shared.Next(-20, 55),
                summaries[Random.Shared.Next(summaries.Length)]
            ))
            .ToArray();
        return forecast;
    })
    .WithName("GetWeatherForecast")
    .WithOpenApi();
    
    app.UseRouting();
    
    app.UseEndpoints(endpoints =>
                {
                    endpoints.MapGet("/", async context =>
                    {
                        await context.Response.WriteAsync("Hello From ASP.NET Core Web API");
                    });
                    endpoints.MapGet("/Resource1", async context =>
                    {
                        await context.Response.WriteAsync("Hello From ASP.NET Core Web API Resource1");
                    });
                    endpoints.MapControllerRoute(
                      name: "Admin",
                      pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
                    endpoints.MapControllerRoute(
                      name: "default",
                      pattern: "{controller=Home}/{action=Index}/{id?}");
                });
    
    app.Run();
    
    record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
    {
        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    }
    
    
  6. 新建常量类RoleConstants.cs和UserConstants.cs,提供默认密码和角色信息:

    namespace TeachingWebApi.Utils.Constants
    {
        public static class UserConstants
        {
            public const string DefaultPassword = "123Pa$$word!";
        }
    }
    
    namespace TeachingWebApi.Utils.Constants
    {
        public static class RoleConstants
        {
            public const string AdministratorRole = "Administrator";
            public const string BasicRole = "Basic";
            public const string DefaultPassword = "123Pa$$word!";
        }
    }
    
  7. 安装包Microsoft.EntityFrameworkCore.Relational 和 Microsoft.AspNetCore.Identity.EntityFrameworkCore,选择8.x版本即可;
    安装Microsoft.EntityFrameworkCore.Relational

    安装Microsoft.AspNetCore.Identity.EntityFrameworkCore

  8. 在你的ConnectionString里的.net/后加入你的数据库名称,这样会默认使用你的数据库:
    修改ConnectionString

  9. 新建MongoIdentityDbContext.cs,创建Identity的Users和Roles表:

    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using MongoDB.Bson;
    using MongoDB.Driver;
    using MongoDB.EntityFrameworkCore.Extensions;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    using TeachingWebApi.Models.Identity;
    
    namespace TeachingWebApi.Utils.Data
    {
        public class MongoIdentityDbContext : DbContext
        {
    
            public MongoIdentityDbContext(DbContextOptions options)
                : base(options)
            {
    
            }
    
            protected override void OnModelCreating(ModelBuilder builder)
            {
                foreach (var property in builder.Model.GetEntityTypes()
                .SelectMany(t => t.GetProperties())
                .Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?)))
                {
                    property.SetColumnType("decimal(18,2)");
                }
    
                foreach (var property in builder.Model.GetEntityTypes()
                    .SelectMany(t => t.GetProperties())
                    .Where(p => p.Name is "LastModifiedBy" or "CreatedBy"))
                {
                    property.SetColumnType("nvarchar(128)");
                }
    
                base.OnModelCreating(builder);
                builder.Entity<TeachingBlazorUser>(entity =>
                {
                    entity.ToTable(name: "Users", "Identity");
                    entity.Property(e => e.Id).ValueGeneratedOnAdd();
                });
    
                builder.Entity<TeachingBlazorRole>(entity =>
                {
                    entity.ToTable(name: "Roles", "Identity").HasKey(x => x.Id);
                });
    
                builder.Entity<IdentityUserClaim<ObjectId>>(entity =>
                {
                    entity.ToTable("UserClaims", "Identity");
                });
    
            }
        }
    }
    
    
  10. 更新DatabaseSeeder.cs,加入自动创建管理员和基础用户的代码:

    using Microsoft.AspNetCore.Identity;
    using MongoDB.Driver;
    using TeachingWebApi.Utils.Data;
    using TeachingWebApi.Models.Identity;
    using TeachingWebApi.Utils.Constants;
    
    namespace TeachingWebApi.Data.Seeder
    {
        public class DatabaseSeeder
        {
            private readonly MongoDbContext _dbContext;
            private readonly UserManager<TeachingBlazorUser> _userManager;
            private readonly RoleManager<TeachingBlazorRole> _roleManager;
            public DatabaseSeeder(
                MongoDbContext dbContext,
                UserManager<TeachingBlazorUser> userManager,
                RoleManager<TeachingBlazorRole> roleManager)
            {
                _dbContext = dbContext;
                _userManager = userManager;
                _roleManager = roleManager;
            }
    
            public void Initialize()
            {
                InitializeCollection();
                AddAdministrator();
                AddBasicUser();
            }
    
            public async void InitializeCollection()
            {
                await CreateCollection("books");
                await CreateCollection("users");
                await CreateCollection("roles");
            }
    
            private void AddAdministrator()
            {
                Task.Run(async () =>
                {
                    //Check if Role Exists
                    var adminRole = new TeachingBlazorRole(RoleConstants.AdministratorRole, "Administrator role with full permissions");
                    var adminRoleInDb = await _roleManager.FindByNameAsync(RoleConstants.AdministratorRole);
                    if (adminRoleInDb == null)
                    {
                        await _roleManager.CreateAsync(adminRole);
                        adminRoleInDb = await _roleManager.FindByNameAsync(RoleConstants.AdministratorRole);
                    }
                    // Check if User Exists
                    var superUser = new TeachingBlazorUser
                    {
                        FirstName = "SuperUser",
                        LastName = "SuperUser",
                        Email = "SuperUser@163.com",
                        UserName = "SuperUser",
                        EmailConfirmed = true,
                        PhoneNumberConfirmed = true,
                        CreatedOn = DateTime.Now,
                        IsActive = true
                    };
                    var superUserInDb = await _userManager.FindByEmailAsync(superUser.Email);
                    if (superUserInDb == null)
                    {
                        await _userManager.CreateAsync(superUser, UserConstants.DefaultPassword);
                        var result = await _userManager.AddToRoleAsync(superUser, RoleConstants.AdministratorRole);
                        // UpdateClaimsAsync(superUser.Id.ToString());
                    }
                }).GetAwaiter().GetResult();
            }
    
            private void AddBasicUser()
            {
                Task.Run(async () =>
                {
                    //Check if Role Exists
                    var basicRole = new TeachingBlazorRole(RoleConstants.BasicRole, "Basic role with default permissions");
                    var basicRoleInDb = await _roleManager.FindByNameAsync(RoleConstants.BasicRole);
                    if (basicRoleInDb == null)
                    {
                        await _roleManager.CreateAsync(basicRole);
                    }
                    //Check if User Exists
                    var basicUser = new TeachingBlazorUser
                    {
                        FirstName = "BasicUser",
                        LastName = "BasicUser",
                        Email = "basicuser@163.com",
                        UserName = "BasicUser",
                        EmailConfirmed = true,
                        PhoneNumberConfirmed = true,
                        CreatedOn = DateTime.Now,
                        IsActive = true
                    };
                    var basicUserInDb = await _userManager.FindByEmailAsync(basicUser.Email);
                    if (basicUserInDb == null)
                    {
                        await _userManager.CreateAsync(basicUser, UserConstants.DefaultPassword);
                        await _userManager.AddToRoleAsync(basicUser, RoleConstants.BasicRole);
                    }
                }).GetAwaiter().GetResult();
            }
    
            private async Task CreateCollection(string collectionName)
            {
                if (!CollectionExists(_dbContext._db, collectionName))
                {
                    await _dbContext._db.CreateCollectionAsync(collectionName, new CreateCollectionOptions
                    {
                        Capped = false
                    });
                    Console.WriteLine("Collection created!");
                }
            }
    
            private bool CollectionExists(IMongoDatabase database, string collectionName)
            {
                return database.ListCollectionNames().ToList().Contains(collectionName);
            }
        }
    }
    
  11. 运行Web Api应用,可以看到MongoDB上你的数据库已自动新增了users和roles的collections,并且可以看到管理员和基础用户已经添加到users表。

    运行成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值