int userId = (int)WebSecurity.CurrentUserId; if ((this.Session.SessionID != dba.getSessionId(userId)) || dba.getSessionId(userId) == null) { WebSecurity.logout(); return RedirectToAction("Index","Home"); }
所以关键是每次用户登录时我都会将他的sessionID保存到数据库字段中.因此,如果具有相同用户名的某人登录已使用相同用户名登录的某人,则会使用此新会话覆盖该数据库字段.如果DB中的sessionID与登录用户的当前会话ID不同,则将其记录下来.
有可能将这部分代码放在一个地方,还是我必须把它放在我的应用程序中的每一个Action中?
我试过Global.asax:
void Application_BeginRequest(object sender,EventArgs e) { if (Session["ID"] != null) { int userId = Convert.ToInt32(Session["ID"]); if ((this.Session.SessionID != db.getSessionId(userId)) || db.getSessionId(userId) == null) { WebSecurity.logout(); } } }
但是我不能在这里使用Session,也不能使用WebSecurity类,如果我这样做:
void Application_BeginRequest(object sender,EventArgs e) { int userId = (int)WebSecurity.CurrentUserId; if ((this.Session.SessionID != db.getSessionId(userId)) || db.getSessionId(userId) == null) { WebSecurity.logout(); Response.RedirectToRoute("Default"); } }
因为我得到null引用异常.
编辑
我用过这个:
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) { int userId = (int)WebSecurity.CurrentUserId; using (var db = new UsersContext()) { string s = db.getSessionId(userId); if ((filterContext.HttpContext.Session.SessionID != db.getSessionId(userId)) || db.getSessionId(userId) == null) { WebSecurity.logout(); filterContext.Result = new RedirectResult("/Home/Index"); } } }
我不得不使用using语句用于上下文,否则db.getSessionId(userId)返回旧的sessionId.方法是这样的:
public string getSessionId(int userId) { string s = ""; var get = this.UserProfiles.Single(x => x.UserId == userId); s = get.SessionId; return s; }
很奇怪,将不得不阅读为什么会发生这种情况.
除了一件事,一切都很好.我在一个控制器中有一个JsonResult动作,它返回Json,但是因为事件(它在enter事件上的文本框)不能触发POST(我认为它是因为它之前注销)重定向不起作用.它甚至无法发布到Json动作以接收回调和重定向.有什么线索吗?
success: function (data) { if (data.messageSaved) { //data received - OK! } else { // in case data was not received,something went wrong redirect out window.location.href = urlhome; } }
在我使用ActionFilterAttribute之前,我使用代码来检查POST内部的不同会话,当然它可以进行回调,因此如果没有收到数据则重定向..但是现在因为它甚至不能POST并进入方法它只是卡在那里并且不重定向:)
解决方法
public class SingleLoginAuthorizeAttribute : AuthorizeAttribute { protected override bool AuthorizeCore(HttpContextBase httpContext) { bool isAuthorized = base.AuthorizeCore(httpContext); if (isAuthorized) { int userId = (int)WebSecurity.CurrentUserId; if ((filterContext.HttpContext.Session.SessionID != dba.getSessionId(userId)) || dba.getSessionId(userId) == null) { WebSecurity.logout(); isAuthorized = false; filterContext.Result = new RedirectResult("/Home/Index"); } } return isAuthorized; } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext.HttpContext.Request.IsAjaxRequest()) { filterContext.Result = new JsonResult() { Data = FormsAuthentication.LoginUrl,JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } else { base.HandleUnauthorizedRequest(filterContext); } } }
我还要提到,这允许你将其他ActionFilters短路,因为它们在OnAuthorization之后运行.
>转发订单 – OnAuthorization:AuthorizationFilter(范围控制器)
>正向订单 – OnActionExecuting:ActionFilter1(范围全局)
>转发订单 – OnActionExecuting:ActionFilter2(范围控制器)
>转发订单 – OnActionExecuting:ActionFilter3(范围操作)
然后如Rob Lyndon所述,你可以在FilterConfig(MVC4)
public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new SingleLoginAuthorizeAttribute()); } }
然后,当您不想要任何授权时,可以在ActionResult方法或Controller类上使用AllowAnonymouseAttribute以允许匿名访问.
更新
我为你的ajax调用(Get或Post)添加了一种方法来处理超时.你可以这样做:
success: function (jsonResult) { if (jsonResult.indexOf('http') == 0) { window.location = jsonResult; } // do other stuff with the Ajax Result }
这不是最好的方法,但如果你想要更多关于如何做得更好的信息,我会问另一个问题而不是在这个问题上附加更多问题.