ASP.NET Identity, несколько пользователей с одним и тем же именем пользователя, но принадлежащих к разным компаниям. Переопределить FindAsync?
Я новичок в MVC и EF и работаю над проектом, в котором использую Identity для управления пользователями и ролями. В предопределенной функции входа в Visual Studio есть функция FindAsync, используемая для получения пользователя по имени пользователя и паролю. В моем случае может быть несколько пользователей с одинаковыми именем пользователя и паролем, но они будут принадлежать разным компаниям. Я хотел бы знать лучший подход; я должен переопределить функцию FindAsync (и другие функции, если необходимо) и добавить другой параметр, или я должен реализовать управление пользователями и ролями самостоятельно, без идентификации? Или есть другое, даже лучшее решение?
Если лучшим решением является переопределение функции, то я немного не уверен, как мне это сделать, поскольку исходный код для UserManager еще не открыт.
Ниже вы можете найти функцию входа в систему и вынос из моих моделей:
public async Task<ActionResult> Login(Login model, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null)
{
await SignInAsync(user, model.RememberMe);
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
public class Company
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
public class User : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
[Required]
public virtual int CompanyId { get; set; }
[Required]
public virtual Company Company { get; set; }
}
Любая помощь приветствуется!
3 ответа
Я думаю, что я бы создал свою собственную реализацию UserManager
и создать метод, как FindByCompanyAsync(string userName, string password, string companyName)
В этом методе вы можете искать пользователя, получая всех пользователей UserManager и использовать выражение LINQ для фильтрации его по имени пользователя и названию компании.
Я нашел этот поток, который решает ту же проблему, что и мой: Как реализовать многопользовательский вход в систему с использованием ASP.NET Identity
Кажется, это хороший подход, и я постараюсь создать собственную реализацию UserStore, как он это делал.
Я отправил companyId в UserStore и переопределил функцию FindByNameAsync для фильтрации как userName, так и companyId. Что мне не нравится, так это то, что я не могу использовать функцию GetUserAggregateAsync, поскольку она закрыта. Есть ли другие недостатки в моем решении?
public class UserStore : UserStore<User>
{
public int companyId = -1;
public UserStore(DbContext context, int companyId)
: base(context)
{
this.companyId = companyId;
}
public override Task<User> FindByNameAsync(string userName)
{
if (companyId < 0)
{
throw new Exception("There is no companyId associated with the UserStore.");
}
return QueryableExtensions.FirstOrDefaultAsync<User>(QueryableExtensions.Include<User, ICollection<IdentityUserLogin>>(QueryableExtensions.Include<User, ICollection<IdentityUserClaim>>(QueryableExtensions.Include<User, ICollection<IdentityUserRole>>(this.Users, (User u) => u.Roles), (User u) => u.Claims), (User u) => u.Logins), (User u) => u.UserName.ToUpper() == userName.ToUpper() && u.CustomerId == this.companyId);
}
}