Domanda

Come posso salvare qualcosa usando FormsAuthentication? Non voglio per memorizzare UserId tramite URL.

Per esempio, ora ho questo codice:

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

class 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 e ProjectRepository non assomiglia a buon codice ... Forse qualcuno può dare consigli, come memorizzare UserID senza l'utilizzo di URL? Il modo migliore per farlo è salvare gli ID su autorisation, credo. Non trovato alcuna struttura a User.Identity per fare questo ...

UPD

Vi chiedo perdono, ma ho dimenticato di dire che sto usando MVC-3 con vista Razor. E che UserId non è una stringa (User.Identity.Name è una stringa) potrebbe essere GUID o forse il mio proprio oggetto ...

È stato utile?

Soluzione

Salva l'UserID nella proprietà UserData del biglietto FormsAuthentication nel cookie di autorizzazione quando l'utente accede:

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

Si può leggere di nuovo nel metodo PostAuthenticateRequest in 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;
}

Si noti che in questo caso, CustomPrincipal deriva da RolePrincipal (anche se non si sta usando ruoli, penso che è necessario derivare da GenericPrincipal), e aggiunge semplicemente la proprietà UserID e sovraccarichi il costruttore.

Ora, ovunque sia necessario l'UserID nella vostra applicazione, si può fare questo:

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

Altri suggerimenti

Perché non prima fare tutte le chiamate di autorizzazione tramite un'interfaccia. In questo modo tutto il codice che utilizza l'autenticazione non ha bisogno di essere preoccupati per come l'accesso viene eseguito, o come l'Identità è memorizzato, ecc.

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

Implemenation per l'IIdentity GetCurrentUserIdentity potrebbe essere qualsiasi modo che ti piace, ma è comunemente visto come una chiamata a "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 che vedete sono informazioni che vengono recuperate su un utente di appartenenza. Questo è comunemente fatto tramite un MembershipProvider ma naturalmente può essere fatto altri modi.

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

Non sono sicuro di aver capito correttamente alla domanda, ma se ti riferisci a un modo di recuperare chi è l'utente corrente è senza passare attraverso l'URL (ad esempio, http: // localhost / regolatore / azione username = RAMe0 ) allora si può guardare con Thread.CurrentPrincipal.Identity.Name o HttpContext.Current.User

Ci sono sottili differenze tra i due comunque. Guardate qui per ulteriori dettagli.

Utilizzando FormsAuthentication è possibile memorizzare il nome utente nella proprietà User.Identity.Name. Ecco un semplice esempio di quello che probabilmente stai cercando. (Utilizzando lo stesso SetAuth si sta già utilizzando)

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

Questo non richiede di passare il nome utente attraverso un parametro QueryString.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top