ASP.NET MVC 3 使用身份验证
-
26-09-2019 - |
题
如何使用 FormsAuthentication 保存某些内容?我不想通过 URL 存储 UserId。
例如,现在我有这样的代码:
//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
班级:
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 和 ProjectRepository 看起来不像好的代码......也许有人可以提供建议,如何在不使用 URL 的情况下存储 UserID?我认为最好的方法是在自动授权时保存 ID。我在 User.Identity 中没有找到任何属性来执行此操作...
UPD
抱歉,我忘了说我正在使用带有 Razor 视图的 MVC-3。而且 UserId 不是一个字符串(User.Identity.Name 是一个字符串),它可能是 GUID 或者可能是我自己的对象......
解决方案
保存在FormsAuthentication票的在授权cookie中的UserData属性用户ID时在用户登录:
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);
可以读回在PostAuthenticateRequest方法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;
}
请注意,在这种情况下,从RolePrincipal(但如果你不使用的角色,我认为你需要从的GenericPrincipal派生)CustomPrincipal派生,而只是将用户ID属性和过载的构造。
现在,只要您需要的用户名在您的应用程序,你可以这样做:
if(HttpContext.Current.Request.IsAuthenticated)
Guid userID = ((CustomPrincipal)HttpContext.Current.User).UserID;
其他提示
为什么不先通过一个接口所有授权的呼叫。这样,您所有的代码,它使用的身份验证并不需要被关注的登录是如何进行的,或恒等式是如何存储,等等。
public interface IAuthorization
{
bool ValidateUser(LoginUser u, string password);
LoginUser GetCurrentUser();
void LogIn(LoginUser user);
void LogOut();
IIdentity GetCurrentUserIdentity();
}
对于实行的IIdentity的GetCurrentUserIdentity可能是你喜欢的任何方式,但通常被视为一个叫“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....
}
你看到的LoginUser类是被约成员资格用户检索的信息。这是通过的MembershipProvider通常做法,但当然可以做其他的方式。
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;
}
我不确定我是否正确理解了这个问题,但如果您指的是一种检索当前用户是谁而不通过 URL 传递的方法(例如 http://localhost/controller/action?用户名=RAMe0)然后您可以查看使用 Thread.CurrentPrincipal.Identity.Name 或 HttpContext.Current.User
然而,两者之间存在微妙的差异。看 这里 更多细节。
使用FormsAuthentication
你可以存储在User.Identity.Name
属性的用户名。以下是你可能在找什么一个简单的例子。 (使用你已经在使用相同SetAuth
)
public ViewResult Index() {
return View(repository.GetUserProjects(this.User.Identity.Name));
}
此不要求通过用户名在通过查询字符串参数。