Реализация UserManager для использования пользовательского класса и хранимых процедур

весь процесс аутентификации и авторизации моего приложения выполняется с использованием хранимых процедур. Я написал класс со всеми функциями, которые мне нужны, например,GetUsers, Login, AddRole, AddMember, etc. Также страница администратора для управления пользователями, ролями и разрешениями выполняется с помощью этого класса.

мне нужно добавить authentication (Я имею в виду, что authorize атрибут), cookies для входа и выхода из системы и хранения некоторых данных на стороне сервера для каждого входа. Думаю, мне нужно ... реализовать Identity за что?

в таком случае, не могли бы вы помочь мне с его реализацией? Кажется, самое основное, что вам нужно сделать, это реализовать create метод, который передает экземпляр IUserStore в конструктор. Но мне не нужны таблицы для пользователей или ролей, как я могу реализовать этот метод?

это текущий класс, и, пожалуйста, дайте мне знать, если вам нужно увидеть мой пользовательский класс аутентификации, который использует сохраненные процедуры.

public class AppUserManager : UserManager<AppUser>
{
    public AppUserManager(IUserStore<AppUser> store) : base(store) { }
    public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
    {
        //AppUserManager manager = new AppUserManager();
        //return manager;
        return null;
    }
}

3 ответов


As alisabzevari предложил вам реализовать свой достаточно iuserstore.
Вы даже не зависите от определенной структуры хранения и таблицы. Вы можете настроить каждый бит вашего слоя хранения.

Я провел несколько экспериментов и попытался реализовать свой собственный UserManager и RoleManager использование другого хранилища, например Бигги:

файловое хранилище документов для - ... Сеть.

код здесь на GitHub.

Первое, что нужно сделать, это реализовать UserManager где вы можете настроить требования для проверки пароля:

public class AppUserManager : UserManager<AppUser, int>
{
    public AppUserManager (IUserStore<AppUser, int> store): base(store)
    {
        this.UserLockoutEnabledByDefault = false;
        // this.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(10);
        // this.MaxFailedAccessAttemptsBeforeLockout = 10;
        this.UserValidator = new UserValidator<User, int>(this)
        {
        AllowOnlyAlphanumericUserNames = false,
        RequireUniqueEmail = false
        };

        // Configure validation logic for passwords
        this.PasswordValidator = new PasswordValidator
        {
        RequiredLength = 4,
        RequireNonLetterOrDigit = false,
        RequireDigit = false,
        RequireLowercase = false,
        RequireUppercase = false,
        };
    }
}

а затем определите свой IUserStore реализация. Основной метод необходимо реализовать это CreateAsync:

public System.Threading.Tasks.Task CreateAsync(User user)
{
    // Saves the user in your storage.
    return Task.FromResult(user);
}

он получит IUser который вы должны сохранить в своем пользовательском хранилище и вернуть он.

если вы посмотрите на код, у меня есть реализовала вы можете видеть, что я использовал несколько интерфейсов IUserRoleStore, IUserPasswordStore, IUserClaimStore etc и т. д., Поскольку мне нужно было использовать роли и утверждения.

Я также реализовал свой собственные SignInManager.

как только вы определили всю свою реализацию, Вы можете загрузить все на запуск:

app.CreatePerOwinContext<Custom.Identity.UserManager>(() => new Custom.Identity.UserManager(new Custom.Identity.UserStore(folderStorage)));
app.CreatePerOwinContext<Custom.Identity.RoleManager>(() => new Custom.Identity.RoleManager(new Custom.Identity.RoleStore(folderStorage)));
app.CreatePerOwinContext<Custom.Identity.SignInService>((options, context) => new Custom.Identity.SignInService(context.GetUserManager<Custom.Identity.UserManager>(), context.Authentication));

вы можете проверить мой AccountController где я попробуйте проверить пользователя:

var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
    return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
    return View("Lockout");
case SignInStatus.RequiresVerification:
    return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
    ModelState.AddModelError("", "Invalid login attempt.");
    return View(model);
}

один раз PasswordSignInAsync называется, вы заметите несколько способов свой UserManager будет называться. Первый будет FindByNameAsync:

public System.Threading.Tasks.Task<User> FindByNameAsync(string userName)
{
    //Fetch your user using the username.
    return Task.FromResult(user);
}

вам придется реализовать свою хранимую процедуру, я думаю, где вы получите своего пользователя из БД.

тогда другой метод FindByIdAsync будет под названием:

public System.Threading.Tasks.Task<User> FindByIdAsync(int userId)
{
    // Fetch - again - your user from the DB with the Id.
    return Task.FromResult(user);
}

снова вам придется использовать хранимую процедуру чтобы найти пользователя по его ID.

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

Я бы предложил вам вставлять точки останова в каждый метод UserStore и посмотреть,как все сочетается.


вы должны реализовать интерфейс IUserStore. См.в этой статье научиться реализовывать собственные поставщики хранилищ для личности ASP.NET .


вы также можете переопределить методы в своем UserManager класса (например,ApplicationUserManager) для управления авторизацией. Вот пример, который использует custom UserManager.FindAsync логика. The UserManager класс используется ApplicationOAuthProvider класс во время аутентификации.

public class ApplicationUserManager : UserManager<ApplicationUser>
{
    public ApplicationUserManager() : base(new EmptyUserStore()) { }

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    {
        return new ApplicationUserManager();
    }

    public override Task<ApplicationUser> FindAsync(string userName, string password)
    {
        // Authentication logic here.
        throw new NotImplementedException("Authenticate userName and password");

        var result = new ApplicationUser { UserName = userName };
        return Task.FromResult(result);
    }
}

/// <summary>
/// User Store with no implementation. Required for UserManager.
/// </summary>
internal class EmptyUserStore : IUserStore<ApplicationUser>
{
    public Task CreateAsync(ApplicationUser user)
    {
        throw new NotImplementedException();
    }

    public Task DeleteAsync(ApplicationUser user)
    {
        throw new NotImplementedException();
    }

    public Task<ApplicationUser> FindByIdAsync(string userId)
    {
        throw new NotImplementedException();
    }

    public Task<ApplicationUser> FindByNameAsync(string userName)
    {
        throw new NotImplementedException();
    }

    public Task UpdateAsync(ApplicationUser user)
    {
        throw new NotImplementedException();
    }

    public void Dispose()
    {
        // throw new NotImplementedException();
    }
}

отметьте, что эта реализация не использует преимущества IUserStore интерфейс.