Я мог бы использовать некоторую помощь по расширению ASP.Net Identity до некоторой степени простой установки с несколькими арендаторами.Это приложение представляет собой приложение WebForms 4.7.1.Я работаю над статьей Скотта Брэди над этим, но я не могу заставить ее работать в моем коде, который немного отличается от его.Я пытаюсь войти в систему, используя дополнительное свойство (CompanyId) и при регистрации принимаю CompanyId вместе с адресом электронной почты и паролем.Я считаю, что правильно настроил DBContext, но пошаговое выполнение этого кода показывает, что мои функции FindByNameAsync и FindByEmailAsync не содержат введенный мной идентификатор компании.Я явно что-то упустил где-то.Помимо статьи Скотта, я действительно забочусь о любых дополнительных деталях о том, как войти в систему с дополнительным параметром.Мне также неясно, как передать это значение CompanyId в мою signinManager.PasswordSignIn функцию при входе в систему.И во время регистрации, несмотря на мои попытки передать CompanyId, функция вставки не содержит мой введенный CompanyId.
Мой код (который я немного сократил) ниже.Любая помощь в указании, где я иду не так, будет очень признательна:
Register.aspx.cs:
public partial class Register : Page
{
protected void CreateUser_Click(object sender, EventArgs e)
{
var context = HttpContext.Current.GetOwinContext().Get<DecisionLogicIdentity.ApplicationDbContext>();
var signInManager = HttpContext.Current.GetOwinContext().Get<DecisionLogicIdentity.ApplicationSignInManager>();
var userStore = new DecisionLogicIdentity.UserStore<DecisionLogicIdentity.ApplicationUser>(context) { CompanyId = Int32.Parse(CompanyId.Text)};
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var provider = new DpapiDataProtectionProvider("SampleAppName");
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser, int>(provider.Create("SampleTokenName"));
var user = new DecisionLogicIdentity.ApplicationUser()
{
CompanyId = Int32.Parse(CompanyId.Text),
UserName = Email.Text,
Email = Email.Text,
IsExpired = false,
IsDeleted = false
};
IdentityResult result = manager.Create(user, Password.Text);
if (result.Succeeded)
{
user = userStore.FindByEmailAsync(user.Email).GetAwaiter().GetResult();
string code = manager.GenerateEmailConfirmationToken(user.Id);
string callbackUrl = IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id, Request);
manager.SendEmail(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>.");
signInManager.SignIn( user, isPersistent: false, rememberBrowser: false);
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
}
else
{
ErrorMessage.Text = result.Errors.FirstOrDefault();
}
}
}
Логин.aspx.cs:
public partial class Login : Page
{
protected void LogIn(object sender, EventArgs e)
{
if (IsValid)
{
var signinManager = HttpContext.Current.GetOwinContext().GetUserManager<DecisionLogicIdentity.ApplicationSignInManager>();
// This doen't count login failures towards account lockout
// To enable password failures to trigger lockout, change to shouldLockout: true
var result = signinManager.PasswordSignIn(Email.Text, Password.Text, RememberMe.Checked, shouldLockout: true);
switch (result)
{
case SignInStatus.Success:
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
break;
case SignInStatus.LockedOut:
Response.Redirect("~/Lockout.aspx");
break;
case SignInStatus.RequiresVerification:
break;
case SignInStatus.Failure:
default:
FailureText.Text = "Invalid login attempt";
ErrorMessage.Visible = true;
break;
}
}
}
}
UserManager:
public class ApplicationUserManager : UserManager<ApplicationUser, int>
{
public int CompanyId { get; set; }
public bool IsExpired { get; set; }
public bool IsDeleted { get; set; }
public ApplicationUserManager(IUserStore<ApplicationUser, int> store)
: base(store)
{
//this.EmailService = emailService;
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(
new DecisionLogicIdentity.UserStore<ApplicationUser>(
context.Get<ApplicationDbContext>() as DatabaseContext));
...
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
var provider = new DpapiDataProtectionProvider("SampleAppName");
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser, int>(provider.Create("SampleTokenName"));
}
return manager;
}
}
UserSigninManager:
public class ApplicationSignInManager : SignInManager<ApplicationUser, int>
{
public int CompanyId { get; set; }
public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager)
: base(userManager, authenticationManager)
{
}
public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
{
return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
}
public override async Task<SignInStatus> PasswordSignInAsync(string userEmail, string password, bool isPersistent, bool shouldLockout)
{
var user = await UserManager.FindByEmailAsync(userEmail);
if (user != null)
{
if (await UserManager.IsLockedOutAsync(user.Id))
{
return SignInStatus.LockedOut;
}
else
{
//If user is not locked out then process login attempt normally
bool passwordCheck = await UserManager.CheckPasswordAsync(user, password);
if (passwordCheck)
{
//Reset the lockout if successful
if (UserManager.SupportsUserLockout && UserManager.GetAccessFailedCount(user.Id) > 0)
{
UserManager.ResetAccessFailedCount(user.Id);
}
var userIdentity = UserManager.CreateIdentity(user, CookieAuthenticationDefaults.AuthenticationType);
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie, DefaultAuthenticationTypes.TwoFactorCookie);
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, userIdentity);
return SignInStatus.Success;
}
else
{
if (UserManager.SupportsUserLockout && UserManager.GetLockoutEnabled(user.Id))
{
UserManager.AccessFailed(user.Id);
}
}
}
return SignInStatus.Failure;
}
return SignInStatus.Failure;
}
public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
{
return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication);
}
...
}
IdentityUser:
public class IdentityUser : IdentityUser<int,
IdentityUserLogin<int>,
IdentityUserRole<int>,
IdentityUserClaim<int>>, IUser<int>
{
public int CompanyId { get; set; }
public bool IsExpired { get; set; }
public bool IsDeleted { get; set; }
public IdentityUser()
{
Guid.NewGuid().ToString();
}
}
UserStore:
public class UserStore<T> : IUserRoleStore<T, int>,
IUserStore<T, int>,
IUserPasswordStore<T, int>,
IUserEmailStore<T, int>,
IUserLockoutStore<T, int>,
IUserTwoFactorStore<T, int>
where T : IdentityUser
{
private readonly UserRepository<T> _userTable;
private readonly UserRolesRepository _userRolesTable;
public int CompanyId { get; set; }
public bool IsExpired { get; set; }
public bool IsDeleted { get; set; }
public UserStore(DatabaseContext databaseContext)
{
_userTable = new UserRepository<T>(databaseContext);
_userRolesTable = new UserRolesRepository(databaseContext);
}
public Task CreateAsync(T user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
user.CompanyId = this.CompanyId;
return Task.Run(() => _userTable.Insert(user));
}
public Task<T> FindByIdAsync(int userId)
{
if (userId <= 0)
{
throw new ArgumentNullException("userId");
}
return Task.Run(() => _userTable.GeTById(userId));
}
public Task<T> FindByNameAsync(string userName)
{
if (string.IsNullOrEmpty(userName))
{
throw new ArgumentException("Null or empty argument: userName");
}
return Task.Run(() => _userTable.GeTByName(userName, this.CompanyId));
}
public Task<T> FindByEmailAsync(string email)
{
if (String.IsNullOrEmpty(email))
{
throw new ArgumentNullException("email");
}
return Task.Run(() => _userTable.GeTByEmail(email, this.CompanyId));
}
...
}
UserRepository:
public class UserRepository<T> where T : IdentityUser
{
private readonly DatabaseContext _databaseContext;
public UserRepository(DatabaseContext databaseContext)
{
_databaseContext = databaseContext;
}
internal T GeTByName(string userName, int companyId)
{
var user = _databaseContext.SiteUser.SingleOrDefault(u => u.UserName == userName & u.CompanyId == companyId);
if (user != null)
{
T result = (T)Activator.CreateInstance(typeof(T));
result.Id = user.Id;
result.CompanyId = user.CompanyId;
result.UserName = user.UserName;
result.PasswordHash = user.PasswordHash;
result.SecurityStamp = user.SecurityStamp;
result.Email = user.Email;
result.EmailConfirmed = user.EmailConfirmed;
result.PhoneNumber = user.PhoneNumber;
result.PhoneNumberConfirmed = user.PhoneNumberConfirmed;
result.LockoutEnabled = user.LockoutEnabled;
result.LockoutEndDateUtc = user.LockoutEndDateUtc;
result.AccessFailedCount = user.AccessFailedCount;
return result;
}
return null;
}
internal T GeTByEmail(string email, int companyId)
{
var user = _databaseContext.SiteUser.SingleOrDefault(u => u.Email == email & u.CompanyId == companyId);
if (user != null)
{
T result = (T)Activator.CreateInstance(typeof(T));
result.Id = user.Id;
result.CompanyId = user.CompanyId;
result.UserName = user.UserName;
result.PasswordHash = user.PasswordHash;
result.SecurityStamp = user.SecurityStamp;
result.Email = user.Email;
result.EmailConfirmed = user.EmailConfirmed;
result.PhoneNumber = user.PhoneNumber;
result.PhoneNumberConfirmed = user.PhoneNumberConfirmed;
result.LockoutEnabled = user.LockoutEnabled;
result.LockoutEndDateUtc = user.LockoutEndDateUtc;
result.AccessFailedCount = user.AccessFailedCount;
return result;
}
return null;
}
internal int Insert(T user)
{
_databaseContext.SiteUser.Add(new SiteUser
{
Id = user.Id,
UserName = user.UserName,
PasswordHash = user.PasswordHash,
SecurityStamp = user.SecurityStamp,
Email = user.Email,
EmailConfirmed = user.EmailConfirmed,
PhoneNumber = user.PhoneNumber,
PhoneNumberConfirmed = user.PhoneNumberConfirmed,
IsExpired = false,
LockoutEnabled = user.LockoutEnabled,
LockoutEndDateUtc = user.LockoutEndDateUtc,
AccessFailedCount = user.AccessFailedCount
});
return _databaseContext.SaveChanges();
}
...
}
DbContext:
public partial class DatabaseContext : DbContext
{
static string identityDatabase = ConfigurationManager.AppSettings["IdentityDatabase"].ToString();
public DatabaseContext()
: base("name=" + identityDatabase)
{
}
public virtual DbSet<Roles> Roles { get; set; }
public virtual DbSet<SiteUserClaims> SiteUserClaims { get; set; }
public virtual DbSet<SiteUserLogins> SiteUserLogins { get; set; }
public virtual DbSet<SiteUser> SiteUser { get; set; }
public bool RequireUniqueEmail { get; private set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Roles>()
.HasMany(e => e.SiteUser)
.WithMany(e => e.Roles)
.Map(m => m.ToTable("UserRole").MapLeftKey("RoleId").MapRightKey("SiteUserId"));
var user = modelBuilder.Entity<SiteUser>();
user.ToTable("SiteUser")
.HasMany(e => e.SiteUserClaims)
.WithRequired(e => e.SiteUser)
.HasForeignKey(e => e.UserId);
user.ToTable("SiteUser")
.HasMany(e => e.SiteUserLogins)
.WithRequired(e => e.SiteUser)
.HasForeignKey(e => e.UserId);
user.Property(u => u.UserName)
.IsRequired()
.HasMaxLength(256)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("UserNameIndex") { IsUnique = true, Order = 1 }));
user.Property(u => u.CompanyId)
.IsRequired()
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("UserNameIndex") { IsUnique = true, Order = 2 }));
}
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
if (entityEntry != null && entityEntry.State == EntityState.Added)
{
var errors = new List<DbValidationError>();
var user = entityEntry.Entity as SiteUser;
if (user != null)
{
if (this.SiteUser.Any(u => string.Equals(u.UserName, user.UserName) && u.CompanyId == user.CompanyId))
{
errors.Add(new DbValidationError("User", string.Format("Username {0} is already taken for CompanyId {1}", user.UserName, user.CompanyId)));
}
if (this.RequireUniqueEmail && this.SiteUser.Any(u => string.Equals(u.Email, user.Email) && u.CompanyId == user.CompanyId))
{
errors.Add(new DbValidationError("User", string.Format("Email Address {0} is already taken for CompanyId {1}", user.UserName, user.CompanyId)));
}
}
else
{
var role = entityEntry.Entity as IdentityRole;
if (role != null && this.Roles.Any(r => string.Equals(r.Name, role.Name)))
{
errors.Add(new DbValidationError("Role", string.Format("Role {0} already exists", role.Name)));
}
}
if (errors.Any())
{
return new DbEntityValidationResult(entityEntry, errors);
}
}
return new DbEntityValidationResult(entityEntry, new List<DbValidationError>());
}
}
Спасибо!