ASP.NET MVC 3 utilisant L'authentification

Comment puis-je sauvegarder quelque chose en utilisant FormsAuthentication? Je ne veux pas stocker l'id utilisateur par le biais de l'URL.

Par exemple, maintenant, j'ai ce code:

//UserController class:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
  if (repository.ValidateUser(model.Login, model.Password))
  {
    FormsAuthentication.SetAuthCookie(model.Login, model.RememberMe);
    if (Url.IsLocalUrl(returnUrl))
    {
      return Redirect(returnUrl);
    }
    else
    {
      return RedirectToAction("Project", "Index");
    }
  }
  else
  {
     ModelState.AddModelError("", "Incorrect name or password.");
  }
}

return View(model);
}

ProjectController catégorie:

public ViewResult Index()
{
    return View(repository.GetUserProjects(
        this.ControllerContext.HttpContext.User.Identity.Name));
}

ProjectRepository:

ProjectsContext context = new ProjectsContext();
UsersContext uCnt = new UsersContext();

public IEnumerable<Project> GetUserProjects(String username)
{
    if (String.IsNullOrEmpty(username))
        throw new ArgumentNullException("username", "Login is empty");
    return this.uCnt.Users
               .FirstOrDefault(u => u.Login == username)
               .Projects
               .ToList();
}

ProjectController et ProjectRepository ne ressemblent pas à du bon code... Peut-être que quelqu'un peut donner des conseils, comment stocker UserID sans utiliser D'URL? La meilleure façon de le faire est de sauver les identifiants sur autorisation, je pense. Je n'ai trouvé aucune propriété dans Utilisateur.Identité pour ce faire...

UPD

je vous demande pardon, mais j'ai oublié de dire que j'utilise MVC-3 avec Razor view. And that UserId is not a string (User.Identité.Nom est une chaîne de caractères) il pourrait être GUID ou peut-être mon propre objet...

22
demandé sur a_hardin 2010-11-21 13:31:43

4 réponses

enregistrer L'identifiant D'utilisateur dans la propriété UserData du ticket FormsAuthentication dans le cookie d'autorisation lorsque l'utilisateur se connecte:

string userData = userID.ToString();

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, user.Email,
    DateTime.Now, DateTime.Now.AddMinutes(FormsAuthentication.Timeout.TotalMinutes),
    createPersistentCookie, userData);
string hashedTicket = FormsAuthentication.Encrypt(ticket);

HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hashedTicket);
HttpContext.Current.Response.Cookies.Add(cookie);

vous pouvez le relire dans la méthode PostAuthenticateRequest dans Global.asax:

HttpCookie formsCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

if (formsCookie != null)
{
    FormsAuthenticationTicket auth = FormsAuthentication.Decrypt(formsCookie.Value);

    Guid userID = new Guid(auth.UserData);

    var principal = new CustomPrincipal(Roles.Provider.Name, new GenericIdentity(auth.Name), userID);

    Context.User = Thread.CurrentPrincipal = principal;
}

notez que dans ce cas, CustomPrincipal dérive de RolePrincipal (bien que si vous n'utilisez pas Roles, je pense que vous devez dériver de GenericPrincipal), et ajoute simplement la propriété UserID et surcharges le constructeur.

Maintenant, partout où vous avez besoin du nom d'utilisateur dans votre application, vous pouvez faire ceci:

if(HttpContext.Current.Request.IsAuthenticated)
    Guid userID = ((CustomPrincipal)HttpContext.Current.User).UserID;
38
répondu TheNextman 2012-04-23 19:07:56

pourquoi ne pas d'abord faire tous vos appels d'autorisation via une interface. De cette façon, l'ensemble de votre code qui utilise l'authentification n'a pas besoin d'être préoccupé par la façon dont la connexion est effectuée, ou comment l'Identité est stockée, etc.

public interface IAuthorization
{
    bool ValidateUser(LoginUser u, string password);
    LoginUser GetCurrentUser();
    void LogIn(LoginUser user);
    void LogOut();
    IIdentity GetCurrentUserIdentity();
}

implémentation pour L'identité GetCurrentUserIdentity IIdentity peut être de n'importe quelle façon, mais est généralement considéré comme un appel à "HttpContext.Actuel.Utilisateur.L'identité"

public class Authorization : IAuthorization
{
    /// <summary>
    /// Get the IIdentity for the current logged in user
    /// </summary>
    /// <returns>IIdentity</returns>
    public virtual IIdentity GetCurrentUserIdentity()
    {
        return HttpContext.Current.User.Identity;
    }

    /// <summary>
    /// Log the user in
    /// </summary>
    /// <param name="user">User details</param>
    public void LogIn(LoginUser user)
    {
        InvalidCredentialsOnNullUser(user);
        FormsAuthentication.SetAuthCookie(user.Name, false);
    }

    /// <summary>
    /// Log the user out
    /// </summary>
    public void LogOut()
    {
        FormsAuthentication.SignOut();
    }

    private static void InvalidCredentialsOnNullUser(LoginUser user)
    {
        if (user == null)
        {
            throw new InvalidCredentialException("That user doesn't exist or is not valid.");
        }
    }

    // other methods....

}

la classe LoginUser que vous voyez est une information qui est récupérée à propos d'un utilisateur d'abonnement. Cela se fait généralement par L'Intermédiaire d'un MembershipProvider, mais bien sûr, d'autres moyens peuvent être utilisés.

public class LoginUser
{
    public string Name;
    public Guid Key;
    public string EmailAddress;
    public bool IsApproved;
    public bool IsLockedOut;
    public DateTime CreationDate;
    public DateTime? LastLoginDate;
    public DateTime? LastPasswordChangedDate;
}
5
répondu CRice 2011-01-14 03:58:30

Je ne suis pas sûr de comprendre la question correctement mais si vous faites référence à une façon de retrouver qui est l'utilisateur actuel sans passer par L'URL (par exemple http://localhost/controller/action?nom d'utilisateur=RAMe0) alors vous pouvez regarder en utilisant le Thread.Principe actuel.Identité.Nom ou HttpContext.Actuel.Utilisateur

il y a cependant des différences subtiles entre les deux. Look ici pour plus de détails.

1
répondu WilliamB 2011-01-10 08:41:07

en utilisant FormsAuthentication vous pouvez stocker le nom d'utilisateur dans le User.Identity.Name propriété. Voici un exemple simple de ce que vous cherchez probablement. (En utilisant le même SetAuth vous utilisez déjà)

public ViewResult Index() {
    return View(repository.GetUserProjects(this.User.Identity.Name));
}

cela ne vous oblige pas à passer le nom d'utilisateur à travers un paramètre QueryString.

1
répondu Buildstarted 2011-01-11 03:56:01