ASP.NET MVC 3 usando autenticação
-
26-09-2019 - |
Pergunta
Como posso salvar algo usando o formsauthenticação? Não quero armazenar o UserID através do URL's.
Por exemplo, agora eu tenho 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
classe:
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 não se parecem com um bom código ... talvez alguém possa dar conselhos, como armazenar o UserID sem usar o URL's? A melhor maneira de fazer isso é salvar IDs na autorização, eu acho. Não encontrei nenhuma propriedade no user.entity para fazer isso ...
Up
Eu imploro um perdão, mas esqueci de dizer que estou usando o MVC-3 com a View Razor. E esse IDID não é uma string (user.identity.name é uma string), pode ser guia ou talvez meu próprio objeto ...
Solução
Salve o UserID na propriedade UserData do ticket FormSauthentication no cookie de autorização quando o usuário efetua login:
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);
Você pode lê -lo de volta no método pós -autenticaterequest em 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;
}
Observe que, nesse caso, o CustomPrincipal deriva do RolePrincipal (embora se você não estiver usando funções, acho que precisa derivar do GenericPrincipal) e simplesmente adicionar a propriedade UserID e sobrecarregar o construtor.
Agora, onde quer que você precise do UserID em seu aplicativo, você pode fazer isso:
if(HttpContext.Current.Request.IsAuthenticated)
Guid userID = ((CustomPrincipal)HttpContext.Current.User).UserID;
Outras dicas
Por que não fazer todas as suas chamadas de autorização por meio de uma interface. Dessa forma, todo o seu código que usa a autenticação não precisa se preocupar com a execução do login, ou como a indentidade é armazenada etc.
public interface IAuthorization
{
bool ValidateUser(LoginUser u, string password);
LoginUser GetCurrentUser();
void LogIn(LoginUser user);
void LogOut();
IIdentity GetCurrentUserIdentity();
}
A implementação para a Ientidade GetCurrentUSerIdentity pode ser da maneira que você quiser, mas é comumente vista como um chamado para "httpcontext.current.user.entity"
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....
}
A classe LoginUser que você vê são informações que são recuperadas sobre um usuário de associação. Isso geralmente é feito por meio de um associação, mas é claro que pode ser feito outras maneiras.
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;
}
Não tenho certeza se entendi a pergunta corretamente, mas se você estiver se referindo a uma maneira de recuperar quem o usuário atual está sem passá -lo pelo URL (por exemplo, http: // localhost/controlador/ação? nome de usuário = rame0) então você pode olhar para o uso de thread.currentprincipal.identity.name ou httpcontext.current.user
Existem diferenças sutis entre os dois, no entanto. Olhar aqui para mais detalhes.
Usando FormsAuthentication
você pode armazenar o nome de usuário no User.Identity.Name
propriedade. Aqui está um exemplo simples do que você provavelmente está procurando. (Usando o mesmo SetAuth
você já está usando)
public ViewResult Index() {
return View(repository.GetUserProjects(this.User.Identity.Name));
}
Isso não exige que você passe o nome de usuário através de um parâmetro de consulta.