2010-02-24 6 views
8

Je tente de créer un schéma d'authentification personnalisé dans ASP.NET MVC à l'aide de l'authentification par formulaire. L'idée que je pourrais avoir différentes zones sur le site qui sera géré - approver sont et la zone de l'utilisateur général, et ceux-ci utiliseront différentes pages de connexion, et ainsi de suite. Donc c'est ce que je veux arriver.Schéma d'authentification/autorisation de formulaire personnalisé dans ASP.net MVC

  1. accès utilisateur restreint la page (en ce moment je l'ai protégé par un AuthorizeAttribute client)
  2. L'utilisateur est redirigé vers une page de connexion spécifique (pas le un de Web.config).
  3. informations d'identification de l'utilisateur sont vérifiées (via système Databse personnalisé) et les journaux utilisateur dans.

apprécierions vraiment d'aide avec ça !!!

C'est ce que je ce que j'ai à ce jour, et il ne fonctionne pas:

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 }; 

     } 
    } 
} 

Répondre

15

J'ai utilisé une combinaison de codes suggéré par minus4 et mon propre code ci-dessus pour créer ce scénario simplifié qui pourrait aider quelqu'un d'autre. J'ai ajouté quelques commentaires sur des choses qui m'ont troublé au début.

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

Le code d'autorisation de formes est grand. Mais une chose à savoir, je crois que c'est la meilleure pratique de rediriger seulement vers une url si elle est locale. Cela atténue la possibilité d'une attaque de redirection. Voir: http://www.asp.net/mvc/tutorials/security/preventing-open-redirection-attacks –

0

i abordé celui-ci avant d'avoir une classe que j'utilise pour se connecter

routines se connecter, lisez biscuit, vérifier cookie et ils ont un modèle qui contient

nom

, email, id, userlevel

alors vous avez juste votre propre coutume ActionFilter

par exemple [CustomAuth (MinAllowedLevel = 10)]

i utiliser un baseclass pour tous mes contrôleurs pour que je puisse avoir un lien plus facile à tout mon contenu de la session et peut alors obtenir des informations comme si

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

je vais bob le tommorow de code si vous voulez pour vous quand je suis de retour sur la journée Royaume-Uni

dire 10 heures je vais vous laisser la classe pour tous les trucs de la session et le filtre d'action personnalisé que vous pouvez utiliser, alors tout ce dont vous avez besoin est un identifiant s table avec un domaine userlevel, mieux avec des niveaux de 10,20,30,40 en cas de besoin vous avez besoin d'un niveau entre 1 et 2

+0

Merci, impatient de voir le code! –

2

N'est ce pas à quoi servent les rôles? Jetez un oeil à asp.net mvc authorization using roles ou jeter un oeil à des rôles en général

+1

Eh bien, pas exactement, si vous avez des zones de connexion complètement séparées au sein de votre site qui ne doivent pas être mélangées ensemble et nécessitent une connexion différente pour chacun, vous ne pouvez pas utiliser les rôles. Par exemple, si vous avez des options d'administrateur pour un site Web (qui ne devrait jamais être visible pour les visiteurs) ainsi que des comptes clients pour l'utilisation du site Web. Lorsque vous cliquez sur les pages sécurisées sans vous connecter, les utilisateurs doivent être redirigés vers différents écrans de connexion en fonction de la zone à laquelle ils accèdent. –

+0

Merci pour la clarification ... – spaceman

3

bien ici, vous allez The Code

là vous avez dossier ActionFilters (AuthAccess.cs) dossier Plugins (de security.cs (Crypter/décrypter cookies), SessionHandler.cs (toutes les questions de connexion)) dossier Controllers (BaseController.cs et exampleController (vous montrer comment utiliser) et le loginTable fichier SQL.

i Majeures donc vous devrez peut-être modifier, aussi j'utilise subsonic donc mon modèle viendrait de là et serait dans le dossier des modèles vides.

vraiment simple à utiliser va laisser pendant un certain temps pour vous, profitez

Nope modèle cookie est ici désolé:

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

Merci beaucoup, le code a aidé. J'ai apporté quelques modifications pour le simplifier et l'adapter à la question initiale. –

+0

thats cool a été conçu comme une base pour un bon départ heureux d'aider – davethecoder

+0

où est le code? le lien ne l'a pas – mamu

Questions connexes