I'll give you an example of the login infrastructure I have here. Basically it's a Controller
, plus the base access providers based on Membership
. It is a somewhat old but well didactic approach.
First of all, install the following NuGet packages into your solution:
link
link
link
Controllers / LoginController.cs
namespace MeuProjeto.Controllers
{
public class LoginController : Controller
{
private MeuProjetoContext _db = new MeuProjetoContext();
//
// GET: /Login/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(UserLogin userLogin)
{
if (ModelState.IsValid && WebSecurity.Login(userLogin.Username, userLogin.Password, persistCookie: true))
{
return RedirectToAction("Index", "Home", new { area = "" });
}
// Se chegou aqui, re-exibir form. Modelo inválido.
ModelState.AddModelError("", "Usuário ou senha incorretos.");
return View(userLogin);
}
public ActionResult RecuperarSenha()
{
ViewBag.ErrorMessage = "";
return View();
}
[HttpPost]
public ActionResult RecuperarSenha(string email)
{
string errorMsg = string.Empty;
if (!string.IsNullOrEmpty(email))
{
List<Usuario> users = _db.Usuarios.Where(usr => usr.Email == email).ToList();
if (users.Count == 0)
{
errorMsg = "E-Mail não encontrado";
}
else
{
Usuario user = users[0];
string url = string.Format("{0}/{1}/{2}", Request.Url.GetLeftPart(UriPartial.Authority), "Login/ResetPassword", user.UsuarioId);
string bodyMail = "Olá " + user.Nome + @"\r\n";
bodyMail += "Para redefinir a sua senha clique <a href=\"" + url + "\">aqui</a><br>";
EmailMessage msg = new EmailMessage();
msg.To = user.Email;
msg.Subject = "Redefinir senha";
msg.Body = bodyMail;
msg.Send();
errorMsg = "E-Mail enviado com sucesso";
}
}
else
{
errorMsg = "E-Mail não pode estar em branco";
}
ViewBag.ErrorMessage = errorMsg;
return View();
}
public ActionResult Logout()
{
WebSecurity.Logout();
return RedirectToAction("Index", "Login", new { area = "" });
}
protected override void Dispose(bool disposing)
{
_db.Dispose();
base.Dispose(disposing);
}
}
}
Web.Config
<system.web>
<roleManager enabled="true" defaultProvider="CustomRoleProvider">
<providers>
<clear />
<add name="CustomRoleProvider" type="MeuProjeto.Site.Infrastructure.CustomRoleProvider" connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</roleManager>
<membership defaultProvider="CustomMembershipProvider">
<providers>
<clear />
<add name="CustomMembershipProvider" type="MeuProjeto.Site.Infrastructure.CustomMembershipProvider" connectionStringName="DefaultConnection" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<sessionState mode="InProc" customProvider="DefaultSessionProvider">
<providers>
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
</providers>
</sessionState>
<customErrors mode="Off" />
</system.web>
Infrastructure / CustomMembershipProvider.cs
using MeuProjeto.Core.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Web;
using System.Web.Configuration;
using System.Web.Security;
using WebMatrix.WebData;
namespace MeuProjeto.Infrastructure
{
public class CustomMembershipProvider : ExtendedMembershipProvider
{
#region Class Variables
private int newPasswordLength = 8;
private string connectionString;
private string applicationName;
private bool enablePasswordReset;
private bool enablePasswordRetrieval;
private bool requiresQuestionAndAnswer;
private bool requiresUniqueEmail;
private int maxInvalidPasswordAttempts;
private int passwordAttemptWindow;
private MembershipPasswordFormat passwordFormat;
private int minRequiredNonAlphanumericCharacters;
private int minRequiredPasswordLength;
private string passwordStrengthRegularExpression;
private MachineKeySection machineKey; //Used when determining encryption key values.
#endregion
static public byte[] RandomSalt
{
get
{
byte[] salt = new byte[48];
using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider())
rngCsp.GetBytes(salt);
return salt;
}
}
private byte[] GeneratePasswordHash(byte[] salt, string password)
{
Byte[] bytes;
using (SHA256 hasher = SHA256.Create())
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
bytes = encoding.GetBytes(password);
hasher.TransformBlock(salt, 0, salt.Length, salt, 0);
hasher.TransformFinalBlock(bytes, 0, bytes.Length);
bytes = hasher.Hash;
}
return bytes;
}
private String GeneratePassword(string newpassword)
{
byte[] salt = RandomSalt;
byte[] passHash = GeneratePasswordHash(salt, newpassword);
// concatenates the salt and hash in one vector
byte[] finalData = new byte[salt.Length + passHash.Length];
Array.Copy(salt, finalData, salt.Length);
Array.Copy(passHash, 0, finalData, salt.Length, passHash.Length);
return System.Convert.ToBase64String(finalData);
}
private bool ByteArraysEqual(byte[] b1, byte[] b2)
{
if (b1 == b2) return true;
if (b1 == null || b2 == null) return false;
if (b1.Length != b2.Length) return false;
for (int i = 0; i < b1.Length; i++)
{
if (b1[i] != b2[i]) return false;
}
return true;
}
public override bool ConfirmAccount(string accountConfirmationToken)
{
throw new NotImplementedException();
}
public override bool ConfirmAccount(string userName, string accountConfirmationToken)
{
throw new NotImplementedException();
}
public override string CreateAccount(string userName, string password, bool requireConfirmationToken)
{
throw new NotImplementedException();
}
public override string CreateUserAndAccount(string userName, string password, bool requireConfirmation, IDictionary<string, object> values)
{
ValidatePasswordEventArgs args = new ValidatePasswordEventArgs(userName, password, true);
OnValidatingPassword(args);
if (args.Cancel)
{
// return MembershipCreateStatus.InvalidPassword;
throw new MembershipCreateUserException(MembershipCreateStatus.InvalidPassword);
}
var CustomMembershipUser = GetUser(userName);
if (CustomMembershipUser == null)
{
// try
// {
using (var context = new MeuProjetoContext())
{
var hashedPassword = GeneratePassword(password);
var user = new Usuario {
UsuarioId = Guid.NewGuid(),
Email = userName,
Nome = values["Name"].ToString(),
Senha = hashedPassword,
Ativo = true
};
context.Usuarios.Add(user);
context.SaveChanges();
var membership = new MeuProjeto.Core.Models.Membership();
membership.MembershipId = Guid.NewGuid();
membership.Usuario = user;
membership.Password = hashedPassword;
context.Memberships.Add(membership);
context.SaveChanges();
return MembershipCreateStatus.Success.ToString();
}
}
else
{
// return MembershipCreateStatus.DuplicateUserName;
throw new MembershipCreateUserException(MembershipCreateStatus.DuplicateUserName);
}
}
public override MembershipUser GetUser(string username, bool userIsOnline = true)
{
CustomMembershipUser CustomMembershipUser = null;
using (var context = new MeuProjetoContext())
{
try
{
var user = context.Usuarios.Where(u => u.Email == username).SingleOrDefault();
if (user != null)
{
CustomMembershipUser = new CustomMembershipUser(
this.Name,
user.Email,
user.UsuarioId,
user.Email,
"",
"",
true,
false,
user.CreatedOn,
DateTime.Now,
DateTime.Now,
default(DateTime),
default(DateTime),
user.Email);
}
}
catch { }
}
return CustomMembershipUser;
}
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
throw new NotImplementedException();
}
public override string GetUserNameByEmail(string email)
{
throw new NotImplementedException();
}
public override int MaxInvalidPasswordAttempts
{
get { throw new NotImplementedException(); }
}
public override int MinRequiredNonAlphanumericCharacters
{
get { throw new NotImplementedException(); }
}
public override int MinRequiredPasswordLength
{
get { throw new NotImplementedException(); }
}
public override int PasswordAttemptWindow
{
get { throw new NotImplementedException(); }
}
public override System.Web.Security.MembershipPasswordFormat PasswordFormat
{
get { throw new NotImplementedException(); }
}
public override string PasswordStrengthRegularExpression
{
get { throw new NotImplementedException(); }
}
public override bool RequiresQuestionAndAnswer
{
get { throw new NotImplementedException(); }
}
public override bool RequiresUniqueEmail
{
get { throw new NotImplementedException(); }
}
public override string ResetPassword(string username, string answer)
{
throw new NotImplementedException();
}
public override bool UnlockUser(string userName)
{
throw new NotImplementedException();
}
public override void UpdateUser(System.Web.Security.MembershipUser user)
{
throw new NotImplementedException();
}
public override bool ValidateUser(string username, string password)
{
using (var context = new MeuProjetoContext())
{
if (context == null) throw new InvalidOperationException();
var user = (from u in context.Usuarios
where u.Email == username && u.Ativo == true
select u).FirstOrDefault();
if (user != null)
{
byte[] pwdHash = GeneratePasswordHash(user.Salt, password);
if (ByteArraysEqual(pwdHash, user.Hash))
{
bool isAdm = true;
System.Web.Security.FormsAuthenticationTicket ticket = new System.Web.Security.FormsAuthenticationTicket(1,
user.UsuarioId.ToString() + "#" + username,
DateTime.Now,
DateTime.Now.AddMinutes(15),
false,
isAdm ? "#" + user.Nome : user.Nome,
System.Web.Security.FormsAuthentication.FormsCookiePath);
#if DEBUG
System.Diagnostics.Debugger.Log(0, "SEC", "User " + username + " logged in at " + ticket.IssueDate.ToString());
#endif
// Encrypt the ticket.
string encTicket = System.Web.Security.FormsAuthentication.Encrypt(ticket);
HttpContext.Current.Response.Cookies.Add(new HttpCookie(System.Web.Security.FormsAuthentication.FormsCookieName, encTicket));
return true;
}
}
return false;
}
}
}
}
Infrastructure / CustomMembershipUser.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
namespace MeuProjeto.Infrastructure
{
public class CustomMembershipUser : MembershipUser
{
public string Name { get; set; }
public CustomMembershipUser(
string providername,
string username,
object providerUserKey,
string email,
string passwordQuestion,
string comment,
bool isApproved,
bool isLockedOut,
DateTime creationDate,
DateTime lastLoginDate,
DateTime lastActivityDate,
DateTime lastPasswordChangedDate,
DateTime lastLockedOutDate,
// int companyFK,
string name) :
base(providername,
username,
providerUserKey,
email,
passwordQuestion,
comment,
isApproved,
isLockedOut,
creationDate,
lastLoginDate,
lastPasswordChangedDate,
lastActivityDate,
lastLockedOutDate)
{
// CompanyFK = companyFK;
Name = name;
}
}
}
Infrastructure / CustomRoleProvider.cs
using MeuProjeto.Core.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
namespace MeuProjeto.Infrastructure
{
public class CustomRoleProvider : RoleProvider
{
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
try
{
using (var context = new MeuProjetoContext())
{
foreach (string username in usernames)
{
// find each user in users table
var user = context.Usuarios.Where(u => u.Email == username).FirstOrDefault();
if (user != null)
{
// find all roles that are contained in the roleNames
var AllDbRoles = context.Roles.ToList();
List<Role> UserRoles = new List<Role>();
foreach (var roleName in roleNames)
{
var role = context.Roles.SingleOrDefault(r => r.Name == roleName);
if (role == default(Role))
{
throw new Exception("Role does not exist.");
}
UserRoles.Add(role);
}
if (UserRoles.Count > 0)
{
foreach (var role in UserRoles)
{
if (!context.UserRoles.Where(ur => ur.UsuarioId == user.UsuarioId && ur.RoleId == role.RoleId).Any())
{
var userRole = new UserRole();
userRole.UserRoleId = Guid.NewGuid();
userRole.Usuario = user;
userRole.Role = role;
context.UserRoles.Add(userRole);
context.SaveChanges();
}
}
}
}
}
}
}
catch (Exception e)
{
throw e;
}
}
public override void CreateRole(string roleName)
{
try
{
if (!RoleExists(roleName))
{
using (var context = new MeuProjetoContext())
{
Role role = new Role();
role.RoleId = Guid.NewGuid();
role.Name = roleName;
context.Roles.Add(role);
context.SaveChanges();
}
}
}
catch (Exception e)
{
throw e;
}
}
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
using (var context = new MeuProjetoContext())
{
try
{
Role role = context.Roles.Where(r => r.Name == roleName).SingleOrDefault();
if (role != null)
{
context.Roles.Remove(role);
context.SaveChanges();
return true;
}
}
catch
{
return false;
}
}
return false;
}
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
List<string> users = new List<string>();
using (var context = new MeuProjetoContext())
{
try
{
var usersInRole = context.UserRoles.Where(ur => ur.Role.Name == roleName && ur.Usuario.Email == usernameToMatch).ToList();
if (usersInRole != null)
{
foreach (var userInRole in usersInRole)
{
users.Add(userInRole.Usuario.Email);
}
}
}
catch { }
}
return users.ToArray();
}
public override string[] GetAllRoles()
{
List<string> roles = new List<string>();
using (var context = new MeuProjetoContext())
{
try
{
var dbRoles = context.Roles.ToList();
foreach (var role in dbRoles)
{
roles.Add(role.Name);
}
}
catch { }
}
return roles.ToArray();
}
public override string[] GetRolesForUser(string username)
{
List<string> roles = new List<string>();
using (var context = new MeuProjetoContext())
{
try
{
var dbRoles = context.UserRoles.Where(r => r.Usuario.Email == username).ToList();
foreach (var role in dbRoles)
{
roles.Add(role.Role.Name);
}
}
catch { }
}
return roles.ToArray();
}
public override string[] GetUsersInRole(string roleName)
{
List<string> users = new List<string>();
using (var context = new MeuProjetoContext())
{
try
{
var usersInRole = context.UserRoles.Where(ur => ur.Role.Name == roleName).ToList();
if (usersInRole != null)
{
foreach (var userInRole in usersInRole)
{
users.Add(userInRole.Usuario.Email);
}
}
}
catch { }
}
return users.ToArray();
}
public override bool IsUserInRole(string username, string roleName)
{
using (var context = new MeuProjetoContext())
{
try
{
var usersInRole = context.UserRoles.SingleOrDefault(ur => ur.Usuario.Email == username && ur.Role.Name == roleName);
if (usersInRole != default(UserRole))
{
return true;
}
}
catch (Exception ex)
{
throw ex;
}
}
return false;
}
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
try
{
using (var context = new MeuProjetoContext())
{
foreach (string username in usernames)
{
// find each user in users table
var user = context.Usuarios.Where(u => u.Email == username).SingleOrDefault();
if (user != null)
{
// find all roles that are contained in the roleNames
var AllDbRoles = context.Roles.ToList();
List<Role> RemoveRoles = new List<Role>();
foreach (var role in AllDbRoles)
{
foreach (string roleName in roleNames)
{
if (role.Name == roleName)
{
RemoveRoles.Add(role);
continue;
}
}
}
if (RemoveRoles.Count > 0)
{
foreach (var role in RemoveRoles)
{
UserRole userRole = context.UserRoles
.Where(ur => ur.UsuarioId == user.UsuarioId && ur.RoleId == role.RoleId)
.SingleOrDefault();
if (userRole != null)
{
context.UserRoles.Remove(userRole);
context.SaveChanges();
}
}
}
}
}
}
}
catch { }
}
public override bool RoleExists(string roleName)
{
using (var context = new MeuProjetoContext())
{
// check if role exits
return context.Roles.Any(r => r.Name == roleName);
}
}
}
}
If you need implementation help, just talk.