I created a functionality that simultaneously prevents multiple logins for a single username, and I call it in Actions as follows:
int userId = (int)WebSecurity.CurrentUserId; if ((this.Session.SessionID != dba.getSessionId(userId)) || dba.getSessionId(userId) == null) { WebSecurity.Logout(); return RedirectToAction("Index", "Home"); }
So, the fact is that every time a user logs in, I save his sessionID in the database field. Therefore, if someone with the same username logs in through someone who is already logged in with the same username, he overwrites this database field with this new session. If the sessionID in the database does not match the current session ID for the registered user, exit it.
Is it possible to put this part of the code in 1 place or do I need to put it in every action in my application?
I tried in 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(); } } }
But I cannot use Session here and the WebSecurity class if I try like this:
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"); } }
because I get a link reference exception.
EDIT
I used this:
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"); } } }
I had to use the using statement for context, otherwise db.getSessionId (userId) returned the old sessionId. The method is as follows:
public string getSessionId(int userId) { string s = ""; var get = this.UserProfiles.Single(x => x.UserId == userId); s = get.SessionId; return s; }
Very strange, you will need to read why this happened.
Everything works fine except for one. I have one JsonResult action in the controller that returns Json, but since the event (its text box on the input of the event) cannot trigger POST (I assume because it logs out earlier), the redirect does not work. He can't even post this Json action to receive callback and redirect. Any clues about this?
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; } }
Before I used ActionFilterAttribute, I used the code to check for different sessions inside POST and, of course, it could make a callback and therefore redirect if it didn't receive the data. But now, since it cannot even POST and go to the method, it just keeps there and does not redirect :)