我有一个MVC项目,我使用表单身份验证,我必须为某些页面实现角色,所以我在global.asax
中得到了这个:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null || authCookie.Value == "")
{
return;
}
FormsAuthenticationTicket authTicket;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch
{
return;
}
string[] roles = authTicket.UserData.Split(';');
if (Context.User != null)
{
Context.User = new GenericPrincipal(Context.User.Identity, roles);
}
}
我在登录模型时保存了用户角色:
//After checking login/password
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(FormsAuthentication.FormsCookieName);
if (cookie == null)
{
cookie = new HttpCookie(FormsAuthentication.FormsCookieName);
HttpContext.Current.Response.Cookies.Add(cookie);
}
string userRoles = null;
if (users[i].PerfilID == UserRanks.Admin)
{
userRoles = "Admin;Users";
}
else
{
userRoles = "Users";
}
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(0,
users[i].Name,
DateTime.Now,
DateTime.Now.AddDays(1),
false,
userRoles,
FormsAuthentication.FormsCookiePath
);
cookie.Value = FormsAuthentication.Encrypt(ticket);
HttpContext.Current.Response.Cookies.Set(cookie);
HttpContext.Current.Session["UserID"] = users[i].UserID;
HttpContext.Current.Session["LastLogin"] = users[i].LastLogin;
HttpContext.Current.User = new GenericPrincipal(HttpContext.Current.User.Identity, userRoles.Split(';'));
要检索会话变量的值,我有一个静态属性:
public static int UserID
{
get
{
object sessionData = HttpContext.Current.Session["UserID"];
if (sessionData == null)
{
//I had something here...
return 0;
}
return Convert.ToInt32(sessionData);
}
private set { }
}
在我实现角色授权之前,我曾经将用户ID保存在cookie userData中,如果会话中的UserID被请求时为null,我将从cookie中检索它(并将其设置为会议再次)。 现在userData正在用于角色管理,我遇到的会话问题比cookie过期时间更快,我有用户登录,我无法检索他们的用户ID,因此无法进行所有操作
所以我必须在每个控制器功能中放置一个检查器,例如:
if (MyUser.Session.UserID == 0)
{
//redirect to Login
}
...我猜错了使用[Authorize]
的全部目的。
有没有更好的方法来处理登录过期和这样的会话变量?
我考虑过使用JSON或其他格式并在cookie中保存一堆userData,但如果可能的话,我想要更简单的东西。
另外,我在登录时这样做:
HttpContext.Current.User = new GenericPrincipal(HttpContext.Current.User.Identity, userRoles.Split(';'));
这似乎与AuthenticateRequest的相同(我从其他地方获得了那部分,似乎是处理成员角色的推荐方法),但它并没有像它应该的那样工作。如果我只留下(并删除[Authorize(Roles="Admin")]
部分),用户始终会被重定向到[Authorize]
甚至仅global.asax
的功能。为什么呢?