如何在ASP.NET Core 2.2中实现身份

时间:2019-01-31 22:45:10

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

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

因此,我正在尝试实现身份

我在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,并且调试控制台显示以下异常:

  • 'System.InvalidOperationException' in Microsoft.Extensions.DependencyInjection.Abstractions.dll
  • 'System.AggregateException' in System.Private.CoreLib.dll

我不知道该如何解决。

我也找到了所有这些问题(及其答案)12345,{{3} }以及这些非SO 67。但是我的主要问题是每个人都使用不同的方式来实现身份(其中一些人过时了2.2),我不知道哪个更好,甚至有些人在我的项目中提出错误,或者我不明白根本没有,所以我尝试这样做(我读到在性能方面,在Program中执行此代码要好于Startup)。

顺便说一句,我还尝试从Programm删除我的代码,而是从Configure的{​​{1}}方法中添加参数Startup和:

IServiceProvider serviceProvider

2 个答案:

答案 0 :(得分:0)

运行代码将在以下行显示异常:

var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();

基于例外情况,您似乎缺少startup.cs文件中用于启用身份的配置。我看不到您的startup.cs,但我怀疑您错过了整个services.AddIdentity(...)的电话。

我建议您花一些时间来阅读如何在ASP.NET Core中配置身份。 Microsoft Docs总是一个很好的起点。

此外,您在问题中提到的second question有很好的步骤。您特别需要查看步骤2和步骤3。

答案 1 :(得分:0)

问题是您试图从IServiceProvider检索范围服务而不创建范围。有趣的是,您围绕对Seed.CreateRoles的调用创建了一个作用域,但随后传入了IServiceProvider,但没有作用域。

您应该做的是要么传入IServiceProvider并在您的Seed.CreateRoles方法内创建范围 ,要么将范围创建保留在当前位置,而直接传递您的范围服务,即RoleManagerUserManager

修改

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

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