Как реализовать идентичность в ASP.NET Core 2.2 - PullRequest
0 голосов
/ 01 февраля 2019

На моем веб-сайте я хочу разрешить администратору войти в систему с учетной записью, чтобы изменить базу данных.Кроме того, я мог бы добавить некоторые роли и учетные записи в будущем.

Итак, я пытаюсь реализовать identity .

Я сделал проект в Visual Studio 2019 (неконечно, если это важно) и выберите ASP.NET Core 2.2 (я установил Core 2.2 самостоятельно) с MVC, аутентификацией с отдельными учетными записями пользователей, и я позволил щелкнуть поле, которое гласило: «настроить для 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

Я не знаю, как это исправить.

Кроме того, я нашел все эти вопросы (с их ответами) 1 , 2 , 3 , 4 , 5 , 6 и эти не-SO 7 и 8 .Но моя главная проблема с ними заключается в том, что каждый из них использует свой способ реализации идентификаторов (некоторые из них устарели до версии 2.2), и я не знаю, какой из них лучше, даже некоторые из них вызывают ошибку в моем проекте, или я не понимаювообще, поэтому я попытался сделать это (я читал, что выполнение этого кода в Program лучше, чем Startup в исполнении).

Кстати, я также пытался удалить свой код из Programm и вместо этого добавьте в метод Configure из Startup параметр IServiceProvider serviceProvider и:

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

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Проблема в том, что вы пытаетесь получить сервисы с областью действия IServiceProvider без создания области действия.Интересно, что вы создали область вокруг своего вызова на Seed.CreateRoles, но затем передаете IServiceProvider, который не ограничен областью действия.

То, что вы должны сделать, это либо передать IServiceProvider и создать область внутри вашего Seed.CreateRoles метода или оставьте создание области там, где оно есть сейчас, и вместо этого передайте ваши сервисы с областью действия, то есть RoleManager и UserManager.

Редактировать

Вам необходимо выполнить одно из следующих действий:

  1. Inject IServiceProvider, а затем создать область видимости внутри метода seed:

    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();
    
0 голосов
/ 01 февраля 2019

Выполнение вашего кода показывает исключение в следующей строке:

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

В зависимости от исключения выясняется, что вам не хватает конфигурации в файле startup.cs для включения Identity.Я не вижу ваши startup.cs, но подозреваю, что вы пропускаете все services.AddIdentity(...) звонки.

Я предлагаю вам уделить некоторое время, чтобы узнать, как настроить Identity в ASP.NET Core. Документы Microsoft - это всегда хорошее место для начала.

Кроме того, второй вопрос , который вы упомянули в своем вопросе, имеет хорошие шаги.Вам конкретно нужно взглянуть на Шаг 2 и Шаг 3.

...