Question

Comment puis-je enregistrer quelque chose en utilisant FormsAuthentication? Je ne veux pas stocker UserId par 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);
}

classe ProjectController:

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 ne ProjectRepository considère pas comme le bon code ... Peut-être que quelqu'un peut donner des conseils, comment stocker UserID sans utiliser les URL? La meilleure façon de le faire est d'économie d'ID sur authorization, je pense. Je ne trouve pas de propriétés à User.Identity pour le faire ...

UPD

Je vous demande pardon, mais j'ai oublié de dire que j'utilise MVC-3 avec vue Razor. Et ce UserId est pas une chaîne (User.Identity.Name est une chaîne), il pourrait être GUID ou peut-être mon propre objet ...

Était-ce utile?

La solution

Enregistrer l'ID utilisateur dans la propriété UserData du ticket FormsAuthentication dans le cookie d'autorisation lorsque l'utilisateur se connecte sur:

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 lire en arrière 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 (mais si vous ne l'utilisez des rôles, je crois que vous devez tirer de GenericPrincipal), et ajoute simplement la propriété ID utilisateur et constructeur surcharges.

Maintenant, chaque fois que vous avez besoin du code d'utilisateur dans votre application, vous pouvez faire ceci:

if(HttpContext.Current.Request.IsAuthenticated)
    Guid userID = ((CustomPrincipal)HttpContext.Current.User).UserID;

Autres conseils

Pourquoi ne pas d'abord faire tous vos appels d'autorisation via une interface. De cette façon, tout le 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 le Indentity est stocké, etc.

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

Implemenation pour la IIdentity GetCurrentUserIdentity pourrait être comme bon vous semble, mais il est généralement considéré comme un appel à « HttpContext.Current.User.Identity »

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 récupérée sur un utilisateur d'adhésion. Cela se fait couramment par un MembershipProvider mais bien sûr, peut être fait d'autres façons.

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

Je ne suis pas sûr que je comprends bien la question, mais si vous faites référence à un moyen de récupérer l'utilisateur qui est en cours sans passer à travers l'URL (par exemple http: // localhost / contrôleur / action nom d'utilisateur = RAMe0 ), vous pouvez regarder à l'aide Thread.CurrentPrincipal.Identity.Name ou HttpContext.Current.User

Il existe des différences subtiles entre les deux cependant. Regardez pour plus de détails.

Utilisation FormsAuthentication vous pouvez stocker le nom d'utilisateur dans la propriété User.Identity.Name. Voici un exemple simple de ce que vous cherchez probablement. (En utilisant la 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 via un paramètre QueryString.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top