ASP.NET MVC 3 usando autenticación


¿Cómo puedo guardar algo usando FormsAuthentication? No quiero almacenar ID de usuario a través de URL.

Por ejemplo, ahora tengo este código:

//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 clase:

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 y ProjectRepository no parecen un buen código... Tal vez alguien puede dar consejos, cómo almacenar userId sin usar URL? La mejor manera de hacer esto es guardar identificaciones en la autorización, creo. No he encontrado ninguna propiedad en User.Identidad que hacer este...

UPD

Le pido perdón, pero me olvidé de decir que estoy usando MVC-3 con Razor view. Y ese userId no es una cadena (User.Identity.Name es una cadena) podría ser GUID o tal vez mi propio objeto...

Author: a_hardin, 2010-11-21

4 answers

Guarde el userId en la propiedad UserData del ticket FormsAuthentication en la cookie de autorización cuando el usuario inicie sesión:

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

Puede leerlo en el método PostAuthenticateRequest en 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;
}

Tenga en cuenta que en este caso, CustomPrincipal deriva de RolePrincipal (aunque si no está utilizando Roles, creo que necesita derivar de GenericPrincipal), y simplemente agrega la propiedad userId y sobrecarga el constructor.

Ahora, dondequiera que necesita el ID de usuario en su aplicación, puede hacer esto:

if(HttpContext.Current.Request.IsAuthenticated)
    Guid userID = ((CustomPrincipal)HttpContext.Current.User).UserID;
 38
Author: TheNextman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-23 19:07:56

¿Por qué no hacer primero todas sus llamadas de autorización a través de una interfaz? De esta manera, todo el código que usa autenticación no necesita preocuparse por cómo se realiza el inicio de sesión, o cómo se almacena la identidad, etc.

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

La implementación para la IIdentity GetCurrentUserIdentity podría ser de la manera que desee, pero se ve comúnmente como una llamada a "HttpContext.Actual.Usuario.Identidad"

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 clase loginUser que ve es información que se recupera sobre una membresía usuario. Esto se hace comúnmente a través de un Membershiprovider, pero por supuesto se puede hacer de otras maneras.

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
Author: CRice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-14 03:58:30

No estoy seguro de entender la pregunta correctamente, pero si se refiere a una forma de recuperar quién es el usuario actual sin pasarlo a través de la URL (por ejemplo, http://localhost/controller/action?username = RAMe0 ) entonces usted puede mirar usando Thread.CurrentPrincipal.Identity.Name o HttpContext.Actual.Usuario

Sin embargo, hay diferencias sutiles entre los dos. Mira aquí para más detalles.

 1
Author: WilliamB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-10 08:41:07

Usando FormsAuthentication puede almacenar el Nombre de usuario en la propiedad User.Identity.Name. Aquí hay un ejemplo simple de lo que probablemente está buscando. (Usando el mismo SetAuth que ya estás usando)

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

Esto no requiere que pase el nombre de usuario a través de un parámetro QueryString.

 1
Author: Buildstarted,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-11 03:56:01