2010-02-24 35 views
8

Estoy intentando crear un esquema de autenticación personalizado en ASP.NET MVC utilizando autenticación de formulario. La idea de que podría tener diferentes áreas en el sitio que se administrarán, aprobador y área de usuario general, y utilizará diferentes páginas de inicio de sesión, y así sucesivamente. Entonces esto es lo que quiero que pase.Autenticación de formulario personalizado/Esquema de autorización en ASP.net MVC

  1. usuario página de acceso restringido (ahora que he protegido con un AuthorizeAttribute cliente)
  2. usuario es redirigido a una página de acceso específico (no el de Web.config).
  3. Las credenciales de usuario se verifican (a través de esquema de Databse personalizado) y usuario inicia sesión en.

realmente apreciaría cualquier ayuda con esto !!!

Esto es lo que lo que tengo hasta ahora, y no funciona:

public class AdministratorAccountController : Controller 
{ 
    public ActionResult Login() 
    { 
     return View("Login"); 
    } 

    [HttpPost] 
    public ActionResult Login(AdministratorAccountModels.LoginModel model, string returnUrl) 
    { 
     if (ModelState.IsValid) 
      if (model.UserName == "admin" && model.Password == "pass") // This will be pulled from DB etc 
      { 
       var ticket = new FormsAuthenticationTicket(1,    // version 
                  model.UserName, // user name 
                  DateTime.Now, // create time 
                  DateTime.Now.AddSeconds(30), // expire time 
                  false,   // persistent 
                  "");    // user data 

       var strEncryptedTicket = FormsAuthentication.Encrypt(ticket); 
       var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, strEncryptedTicket); 
       Response.Cookies.Add(cookie); 

       if (!String.IsNullOrEmpty(returnUrl)) 
       { 
        return Redirect(returnUrl); 
       } 
       else 
       { 
        return RedirectToAction("Index", "Home"); 
       } 
      } 
      else 
      { 
       ModelState.AddModelError("", "The user name or password provided is incorrect."); 
      } 

     // If we got this far, something failed, redisplay form 
     return View(model); 
    } 

    [AdministratorAuthorize] 
    public ActionResult MainMenu() 
    { 
     return View(); 
    } 

    public class AdministratorAuthorizeAttribute : AuthorizeAttribute 
    { 
     protected override bool AuthorizeCore(HttpContextBase httpContext) 
     { 
      var authenCookie = httpContext.Request.Cookies.Get(FormsAuthentication.FormsCookieName); 
      if (authenCookie == null) return false; 

      var ticket = FormsAuthentication.Decrypt(authenCookie.Value); 
      var id = new FormsIdentity(ticket); 
      var astrRoles = ticket.UserData.Split(new[] { ',' }); 
      var principal = new GenericPrincipal(id, astrRoles); 
      httpContext.User = principal; 
      return true; 
     } 

     protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
     { 
      var model = new AdministratorAccountModels.LoginModel(); 
      var viewData = new ViewDataDictionary(model); 

      filterContext.Result = new ViewResult { ViewName = "Login", ViewData = viewData }; 

     } 
    } 
} 

Respuesta

15

He utilizado una combinación de código sugerido por minus4 y mi propio código arriba para crear este escenario simplificado que podría ayudar a alguien más. Agregué algunos comentarios sobre cosas que me confundieron al principio.

public class AdministratorAccountController : Controller 
{ 
    public ActionResult Login() 
    { 
     return View("Login"); 
    } 

    [HttpPost] 
    public ActionResult Login(AdministratorAccountModels.LoginModel model, string returnUrl) 
    { 
     if (ModelState.IsValid) 
      // Here you would call a service to process your authentication 
      if (model.UserName == "admin" && model.Password == "pass") 
      { 
       // * !!! * 
       // Creating a FromsAuthenticationTicket is what 
       // will set RequestContext.HttpContext.Request.IsAuthenticated to True 
       // in the AdminAuthorize attribute code below 
       // * !!! * 
       var ticket = new FormsAuthenticationTicket(1, // version 
                  model.UserName, // user name 
                  DateTime.Now, // create time 
                  DateTime.Now.AddSeconds(30), // expire time 
                  false, // persistent 
                  ""); // user data, such as roles 

       var strEncryptedTicket = FormsAuthentication.Encrypt(ticket); 
       var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, strEncryptedTicket); 
       Response.Cookies.Add(cookie); 

       // Redirect back to the page you were trying to access 
       if (!String.IsNullOrEmpty(returnUrl)) 
       { 
        return Redirect(returnUrl); 
       } 
       else 
       { 
        return RedirectToAction("Index", "Home"); 
       } 
      } 
      else 
      { 
       ModelState.AddModelError("", "The user name or password provided is incorrect."); 
      } 

     // If we got this far, something failed, redisplay form 
     return View(model); 
    } 

    [AdminAuthorize] 
    public ActionResult MainMenu() 
    { 
     return View(); 
    } 

    public class AdminAuthorize : ActionFilterAttribute 
    { 
     public override void OnActionExecuting(ActionExecutingContext filterContext) 
     { 
      if (!filterContext.RequestContext.HttpContext.Request.IsAuthenticated) 
      { 
       // Redirect to the needed login page 
       // This can be pulled from config file or anything else 
       filterContext.HttpContext.Response.Redirect("/AdministratorAccount/Login?ReturnUrl=" 
             + HttpUtility.UrlEncode(filterContext.HttpContext.Request.RawUrl));    
      } 

      base.OnActionExecuting(filterContext); 
     } 
    } 
} 
+1

El código de autenticación de formularios es excelente. Pero una cosa a tener en cuenta, creo que es una buena práctica redirigir solo a una url si es local. Esto mitiga la posibilidad de un ataque de redirección. Ver: http://www.asp.net/mvc/tutorials/security/preventing-open-redirection-attacks –

0

Abordé éste antes de que tenga una clase yo uso para iniciar sesión

rutinas están acceder, leer galleta, galleta y comprobar que tienen un modelo que contenga el nombre

, correo electrónico, identificación, userlevel

a continuación, sólo tiene su propia costumbre actionFilter

por ejemplo, [CustomAuth (MinAllowedLevel = 10)]

i utilizar una clase base para todos mis controladores para que pueda tener un vínculo más fácil de todo mi contenido de la sesión y luego puedo conseguir información como tal

var model = pictures.all().where(x => x.userid == users.ReadCookie.userID) 

voy a bob el tommorow de código si lo desea para que cuando estoy de vuelta en el día Reino Unido

decir 10 horas voy a dejar que usted tiene la clase para todas las cosas de la sesión y el filtro de la acción personalizado que puede utilizar, entonces todo lo que necesitas es un inicio de sesión s tabla con un campo de nivel de usuario, mejor con niveles de 10,20,30,40 en caso de que necesite un nivel entre 1 y 2

+0

Gracias, deseando ver el código! –

2

¿No es esto para qué sirven los roles? un vistazo a asp.net mvc authorization using roles o echar un vistazo a los papeles en general

+1

Bueno, no exactamente, si tiene áreas de inicio de sesión completamente separadas dentro de su sitio que no deben mezclarse entre sí y requieren un inicio de sesión diferente para cada una, no puede usar roles. Por ejemplo, si tiene opciones de administrador para un sitio web (que nunca debería ser visible para los visitantes), así como cuentas de clientes para usar el sitio web. Cuando acceda a las páginas seguras sin iniciar sesión, debería hacer rebotar a los usuarios a diferentes pantallas de inicio de sesión basadas en el área a la que están accediendo. –

+0

Gracias por la aclaración ... – spaceman

3

bien aquí vas The Code

ahí que haya carpeta ActionFilters (AuthAccess.cs) carpeta de plugins (security.cs (cifrar/descifrar galletas), SessionHandler.cs (todos los asuntos de inicio de sesión)) carpeta Controladores (BaseController.cs y EjemploController (que muestran cómo utilizar) y el archivo de SQL loginTable.

i usar MySQL por lo que puede que tenga que modificar, también utilizo subsónico así que mi modelo vendría desde allí y estaría en la carpeta de modelos vacíos.

muy sencillo de utilizar lo dejará por un tiempo para usted, disfrutar de

nop modelo cookie es aquí lo siento:

using System; 

namespace TestApp.Models 
{ 
    public class CookieModel 
{ 
    public string CurrentGuid { get; set; } 
    public DateTime LoginTime { get; set; } 
    public Int32 UserLevel { get; set; } 
    public Int32 LoginID { get; set; } 
    public bool isValidLogin { get; set; } 
    public string realUserName { get; set; } 
    public string emailAddress { get; set; } 
} 
} 
+0

Muchas gracias, el código ayudó. Hice algunos cambios para simplificarlo y ajustarme a la pregunta original. –

+0

thats cool fue una base para un buen comienzo feliz de ayudar – davethecoder

+0

¿dónde está el código? link no lo tiene – mamu

Cuestiones relacionadas