首页 > 解决方案 > 如何在 ASP.NET Core 2.2 中实现标识

问题描述

在我的网站中,我想让管理员使用帐户登录以修改数据库。另外,我将来可能会添加一些角色和帐户。

所以,我正在尝试实现identity

我在 Visual Studio 2019 中创建了一个项目(不确定这是否重要),并选择了带有 MVC 的 ASP.NET Core 2.2(我自己安装了 Core 2.2),使用个人用户帐户进行身份验证,然后我点击了上面写着的框:“配置 HTTPS”。

制作项目后,我打开它,创建一个随机帐户,出现错误,然后迁移数据库以修复它。

然后,我添加appsetting.json

"UserSettings": {
    "UserName": "MyAdminUser",
    "UserEmail": "MyAdminUser@gmail.com",
    "UserPassword": "A_123456a"
}

在文件夹中创建一个新类Data

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace WebApplication1.Data {
    public static class Seed {
        public static async Task CreateRoles(IServiceProvider serviceProvider, IConfiguration Configuration) {
            // Add customs roles
            var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
            // Note: I used IdentityUser instead of make my ApplicationUser as other people do because the default idendity is fine for me, I don't need additional fields nor I want to make this more difficult.
            var UserManager = serviceProvider.GetRequiredService<UserManager<IdentityUser>>();
            string[] roleNames = { "Admin" };
            IdentityResult roleResult;

            foreach (var roleName in roleNames) {
                // Create roles and seeding them to the database
                var roleExist = await RoleManager.RoleExistsAsync(roleName);
                if (!roleExist) {
                    roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
                }
            }

            // Create a super user
            var poweruser = new IdentityUser {
                UserName = Configuration.GetSection("AppSettings")["UserSettings:UserName"],
                Email = Configuration.GetSection("AppSettings")["UserSettings:UserEmail"]
            };

            string userPassword = Configuration.GetSection("AppSettings")["UserSettings:UserPassword"];
            var user = await UserManager.FindByEmailAsync(Configuration.GetSection("AppSettings")["UserSettings:UserEmail"]);

            if (user == null) {
                var createPowerUser = await UserManager.CreateAsync(poweruser, userPassword);
                if (createPowerUser.Succeeded) {
                    // Assign the new user the "Admin" role 
                    await UserManager.AddToRoleAsync(poweruser, "Admin");
                }
            }
        }
    }
}

最后将类的Main方法替换Program为:

public static void Main(string[] args) {
    var host = CreateWebHostBuilder(args).Build();    
    using (var scope = host.Services.CreateScope()) {
        var services = scope.ServiceProvider;
        var serviceProvider = services.GetRequiredService<IServiceProvider>();
        var configuration = services.GetRequiredService<IConfiguration>();
        Seed.CreateRoles(serviceProvider, configuration).Wait();
    }    
    host.Run();
}

但是当我运行它时,HTTP Error 500.30 - ANCM In-Process Start Failure网页上会出现错误,并且调试控制台显示以下异常:

我不知道如何解决这个问题。

此外,我发现了所有这些问题(及其答案)123456以及这些 Non-SO 78。但我对它们的主要问题是每个人都使用不同的方式来实现身份(其中一些已经过时到 2.2)而且我不知道哪个更好,甚至在我的项目中出现一些错误或者我不明白根本没有,所以我尝试这样做(我读到执行此代码比执行此代码Program要好Startup)。

顺便说一句,我还尝试从参数中删除我的代码Programm,而是从参数中添加Configure方法,并且:StartupIServiceProvider serviceProvider

// I used _ = because VS said me something about async
_ = Seed.CreateRoles(serviceProvider, Configuration);

标签: c#asp.netasp.net-core.net-coreasp.net-core-mvc

解决方案


问题是您试图在IServiceProvider不创建范围的情况下从中检索范围服务。有趣的是,您在对 的调用周围创建了一个范围Seed.CreateRoles,但随后您传入了IServiceProvider没有范围的 。

你应该做的是要么传入并你的方法中IServiceProvider创建范围,要么将范围创建留在现在的位置,而是传入你的范围服务,即和.Seed.CreateRolesRoleManagerUserManager

编辑

您需要执行以下操作之一:

  1. 在种子方法中注入IServiceProvider然后创建你的作用域:

    var host = CreateWebHostBuilder(args).Build();
    Seed.CreateRoles(host.Services);
    host.Run();
    

    然后:

    public static async Task CreateRoles(IServiceProvider services) {
        var configuration = services.GetRequiredService<IConfiguration>();
        using (var scope = services.CreateScope())
        {
            var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
            var userManager = scope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>();
    
            // seed data
        }
    }
    
  2. 注入您的范围服务:

    var host = CreateWebHostBuilder(args).Build();
    
    var configuration = host.Services.GetRequiredService<IConfiguration>();
    using (var scope = host.Services.CreateScope())
    {
        var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
        var userManager = scope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>();
        Seed.CreateRoles(configuration, roleManager, userManager);
    }
    host.Run();
    

推荐阅读