Cómo implementar la autenticación personalizada en ASP.NET MVC 5

80

Estoy desarrollando una aplicación ASP.NET MVC 5. Tengo una base de datos existente, a partir de la cual creé mi modelo de datos de entidad ADO.NET. Tengo una tabla en esa base de datos que contiene la columna "nombre de usuario" y "contraseña", y quiero usarlas para implementar la autenticación y autorización en mi aplicación web; No puedo crear ninguna otra base de datos, tabla o columna y no puedo utilizar la autenticación de identidad estándar debido a los requisitos del cliente. No necesito administrar el registro, el cambio de contraseña u otras cosas: solo inicie sesión con contraseña y nombre de usuario. ¿Cómo puedo hacer eso?

Giacomo Santarnecchi
fuente

Respuestas:

158

Sí tu puedes. Las partes de autenticación y autorización funcionan de forma independiente. Si tiene su propio servicio de autenticación, puede usar la parte de autorización de OWIN. Considere que ya tiene un UserManagerque valida usernamey password. Por lo tanto, puede escribir el siguiente código en su acción de inicio de sesión posterior a la devolución:

[HttpPost]
public ActionResult Login(string username, string password)
{
    if (new UserManager().IsValid(username, password))
    {
        var ident = new ClaimsIdentity(
          new[] { 
              // adding following 2 claim just for supporting default antiforgery provider
              new Claim(ClaimTypes.NameIdentifier, username),
              new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),

              new Claim(ClaimTypes.Name,username),

              // optionally you could add roles if any
              new Claim(ClaimTypes.Role, "RoleName"),
              new Claim(ClaimTypes.Role, "AnotherRole"),

          },
          DefaultAuthenticationTypes.ApplicationCookie);

        HttpContext.GetOwinContext().Authentication.SignIn(
           new AuthenticationProperties { IsPersistent = false }, ident);
        return RedirectToAction("MyAction"); // auth succeed 
    }
    // invalid username or password
    ModelState.AddModelError("", "invalid username or password");
    return View();
}

Y su administrador de usuarios puede ser algo como esto:

class UserManager
{
    public bool IsValid(string username, string password)
    {
         using(var db=new MyDbContext()) // use your DbConext
         {
             // for the sake of simplicity I use plain text passwords
             // in real world hashing and salting techniques must be implemented   
             return db.Users.Any(u=>u.Username==username 
                 && u.Password==password); 
         }
    }
}

Al final, puede proteger sus acciones o controladores agregando un Authorizeatributo.

[Authorize]
public ActionResult MySecretAction()
{
    // all authorized users can use this method
    // we have accessed current user principal by calling also
    // HttpContext.User
}

[Authorize(Roles="Admin")]
public ActionResult MySecretAction()
{
    // just Admin users have access to this method
} 
Sam FarajpourGhamari
fuente
7
Acabo de actualizar mi publicación para responder a sus preguntas.
Sam FarajpourGhamari
5
Oye, quería hacerte saber que tu ejemplo de github (para tokenauth) resolvió mis problemas, ¡muchas gracias! Votaría tu ejemplo 1000 veces si pudiera :)
AME
6
paquetes nuget necesarios: - Microsoft.AspNet.Identity.Core - Microsoft.AspNet.Identity.Owin - Microsoft.Owin - Microsoft.Owin.Host.SystemWeb - Microsoft.Owin.Security - Microsoft.Owin.Security.Cookies - Microsoft.Owin .Seguridad.OAuth - Owin
Matthieu
5
Ojalá tuvieras una recompensa abierta para esta pregunta para poder darte +1000. Publique esto en algún lugar del blog para que los motores de búsqueda puedan encontrarlo. Es una solución tan fácil y elegante. Pasé dos días leyendo sobre OWIN y OAuth2 y no pude conectar cables.
adopilot
2
@SamFarajpourGhamari: ¿Puede explicar por qué se requiere esa cadena larga const en el Logincódigo? ... new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string")¡Comprobé que el código funciona bien sin él!
S.Serpooshan