What's the best way to override authentication in MVC 5?
I have a project that has no registration. The administrator registers users as admin. The project has no roles, I only have one type of user. I don't need "AspNetRoles", "AspNetUserClaims", "AspNewUserLogins", "AspNetUserRoles". And in the table "AspNetUsers" I only need "Id", "Email", "Password" and a few custom properties. What's the best way to implement this in mvc 5?
source to share
To add more columns / fields to AspNetUsers , you need to add them to Identity Model adn do Data Migration using command-update database
you can also manage keys and table name by overriding as below
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUser>().ToTable("MyUsers").Property(p => p.Id).HasColumnName("UserId");
modelBuilder.Entity<ApplicationUser>().ToTable("MyUsers").Property(p => p.Id).HasColumnName("UserId");
modelBuilder.Entity<IdentityUserRole>().ToTable("MyUserRoles");
modelBuilder.Entity<IdentityUserLogin>().ToTable("MyUserLogins");
modelBuilder.Entity<IdentityUserClaim>().ToTable("MyUserClaims");
modelBuilder.Entity<IdentityRole>().ToTable("MyRoles");
}
When you use ASPNET Schema to register a user, I don't think you can avoid claims, roles, and other tables, but you can just ignore them.
Update
Avoiding roles and claims in ASPNET membership
First of all create an MVC 5 application. Then execute IUser,
public class ApplicationUser : IUser
{
public ApplicationUser()
{
this.Id = Guid.NewGuid().ToString();
}
public ApplicationUser(string userName): this()
{
UserName = userName;
}
public virtual string Id { get; set; }
public virtual string PasswordHash { get; set; }
public virtual string SecurityStamp { get; set; }
public virtual string UserName { get; set; }
}
Next, we need a DbContet to store the Users,
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
public virtual IDbSet<ApplicationUser> Users { get; set; }
}
and then we need to implement IUserStore, IUserPasswordStore and IUserSecurityStampStore,
public class MyUserStore : IUserStore<ApplicationUser>, IUserPasswordStore<ApplicationUser>, IUserSecurityStampStore<ApplicationUser>
{
UserStore<IdentityUser> userStore = new UserStore<IdentityUser>(new ApplicationDbContext());
public MyUserStore()
{
}
public Task CreateAsync(ApplicationUser user)
{
var context = userStore.Context as ApplicationDbContext;
context.Users.Add(user);
context.Configuration.ValidateOnSaveEnabled = false;
return context.SaveChangesAsync();
}
public Task DeleteAsync(ApplicationUser user)
{
var context = userStore.Context as ApplicationDbContext;
context.Users.Remove(user);
context.Configuration.ValidateOnSaveEnabled = false;
return context.SaveChangesAsync();
}
public Task<ApplicationUser> FindByIdAsync(string userId)
{
var context = userStore.Context as ApplicationDbContext;
return context.Users.Where(u => u.Id.ToLower() == userId.ToLower()).FirstOrDefaultAsync();
}
public Task<ApplicationUser> FindByNameAsync(string userName)
{
var context = userStore.Context as ApplicationDbContext;
return context.Users.Where(u => u.UserName.ToLower() == userName.ToLower()).FirstOrDefaultAsync();
}
public Task UpdateAsync(ApplicationUser user)
{
var context = userStore.Context as ApplicationDbContext;
context.Users.Attach(user);
context.Entry(user).State = EntityState.Modified;
context.Configuration.ValidateOnSaveEnabled = false;
return context.SaveChangesAsync();
}
public void Dispose()
{
userStore.Dispose();
}
public Task<string> GetPasswordHashAsync(ApplicationUser user)
{
var identityUser = ToIdentityUser(user);
var task = userStore.GetPasswordHashAsync(identityUser);
SetApplicationUser(user, identityUser);
return task;
}
public Task<bool> HasPasswordAsync(ApplicationUser user)
{
var identityUser = ToIdentityUser(user);
var task = userStore.HasPasswordAsync(identityUser);
SetApplicationUser(user, identityUser);
return task;
}
public Task SetPasswordHashAsync(ApplicationUser user, string passwordHash)
{
var identityUser = ToIdentityUser(user);
var task = userStore.SetPasswordHashAsync(identityUser, passwordHash);
SetApplicationUser(user, identityUser);
return task;
}
public Task<string> GetSecurityStampAsync(ApplicationUser user)
{
var identityUser = ToIdentityUser(user);
var task = userStore.GetSecurityStampAsync(identityUser);
SetApplicationUser(user, identityUser);
return task;
}
public Task SetSecurityStampAsync(ApplicationUser user, string stamp)
{
var identityUser = ToIdentityUser(user);
var task = userStore.SetSecurityStampAsync(identityUser, stamp);
SetApplicationUser(user, identityUser);
return task;
}
private static void SetApplicationUser(ApplicationUser user, IdentityUser identityUser)
{
user.PasswordHash = identityUser.PasswordHash;
user.SecurityStamp = identityUser.SecurityStamp;
user.Id = identityUser.Id;
user.UserName = identityUser.UserName;
}
private IdentityUser ToIdentityUser(ApplicationUser user)
{
return new IdentityUser
{
Id = user.Id,
PasswordHash = user.PasswordHash,
SecurityStamp = user.SecurityStamp,
UserName = user.UserName
};
}
}
For the password hash and security stamp, I am using the UserStore implementation to simplify the process. Finally, we just need to change the constructor of the AccountController to use our MyUserStore implementation,
public AccountController()
: this(new UserManager<ApplicationUser>(new MyUserStore()))
{
}
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
To remove unnecessary columns in the Users table. You can try something like this
public partial class ModifyUser: DbMigration
{
public override void Up()
{
AddColumn("dbo.AspNetUsers", "NewField", c => c.String());
}
public override void Down()
{
DropColumn("dbo.AspNetUsers", "NewColumn");
}
}
Then in packageManager run PM> update-database
source to share