У меня есть проект MVC 6 (vNext), и я играю с идентификатором ASP.NET. В моем случае я не хочу использовать встроенный материал, который использует EF (SignInManager, UserManager, UserStore). У меня есть внешняя база данных, и я просто хочу найти имя пользователя/пароль и вернуть действительный файл cookie. Поэтому я начал писать свои собственные классы.
public class MyUser
{
public string Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string PasswordHash { get; set; }
}
public class MyUserStore : IUserStore<MyUser>, IUserPasswordStore<MyUser>
{
...
}
В классе MyUserStore
я использую жестко запрограммированный список пользователей в качестве своего магазина (только для тестовых целей). И я перепробовал некоторые методы только для того, чтобы вернуть данные из жестко закодированного хранилища.
public class MyUserManager : UserManager<MyUser>
{
public MyUserManager(
IUserStore<MyUser> store,
IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<MyUser> passwordHasher,
IEnumerable<IUserValidator<MyUser>> userValidators,
IEnumerable<IPasswordValidator<MyUser>> passwordValidators,
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
IEnumerable<IUserTokenProvider<MyUser>> tokenProviders,
ILoggerFactory logger,
IHttpContextAccessor contextAccessor) :
base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, tokenProviders, logger, contextAccessor)
{
}
}
Здесь я сделал методы CheckPasswordAsync
и VerifyPasswordAsync
для возврата true
и PasswordVerificationResult.Success
соответственно только для теста.
public class MyClaimsPrincipleFactory : IUserClaimsPrincipalFactory<MyUser>
{
public Task<ClaimsPrincipal> CreateAsync(MyUser user)
{
return Task.Factory.StartNew(() =>
{
var identity = new ClaimsIdentity();
identity.AddClaim(new Claim(ClaimTypes.Name, user.UserName));
var principle = new ClaimsPrincipal(identity);
return principle;
});
}
}
public class MySignInManager : SignInManager<MyUser>
{
public MySignInManager(MyUserManager userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactory<MyUser> claimsFactory, IOptions<IdentityOptions> optionsAccessor = null, ILoggerFactory logger = null)
: base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger)
{
}
public override Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout)
{
// here goes the external username and password look up
if (userName.ToLower() == "username" && password.ToLower() == "password")
{
return base.PasswordSignInAsync(userName, password, isPersistent, shouldLockout);
}
else
{
return Task.FromResult(SignInResult.Failed);
}
}
}
И все подключено в классе Startup
следующим образом:
services.AddIdentity<MyUser, MyRole>()
.AddUserStore<MyUserStore>()
.AddUserManager<MyUserManager>()
.AddDefaultTokenProviders();
И поскольку мне не удалось создать объект MySignInManager
в коде Startup
, чтобы добавить его в DI (для последующей инъекции в контроллерах и представлениях), я создаю его в MyAccountController
.
public MyAccountController(IHttpContextAccessor httpContextAccessor, UserManager<MyUser> userManager, IOptions<IdentityOptions> optionsAccessor, ILoggerFactory logger)
{
SignInManager = new MySignInManager(userManager as MyUserManager, httpContextAccessor, new MyClaimsPrincipleFactory(), optionsAccessor, logger);
}
В моем действии MyLogin
в контроллере MyAccount
я звоню PasswordSignInAsync
, и я вижу, что я получаю файл cookie с закодированными утверждениями в нем (из MyClaimsPrincipleFactory
).
Когда я пытаюсь вызвать какое-то другое действие с помощью AuthorizeAttribute
на нем, я вижу, что cookie находится в заголовке запроса, но я несанкционирован (точнее, потому что я не удалял встроенную стандартную аутентификацию ASP.NET Identity Authentication из шаблона образца визуальной студии я перенаправлен на учетную запись /Login ).
Является ли это правильным способом настройки ASP.NET Identity и чего я здесь не вижу?