Глобальное событие OnLoggedIn в ASP.net?

Есть ли способ получить уведомление, когда пользователь входит в систему с веб-сайта ASP.net?

Примечание. Пользователь может войти в систему, не заходя на "страницу входа". Если файл cookie "запомнить меня" существует, он может попасть на произвольную страницу и войти в систему.

Когда пользователь вошел в систему, я хочу получить информацию, относящуюся к сеансу.

Примечание: есть Login.LoggedIn событие. Проблема в том, что этот элемент управления существует не на каждой странице; и одна страница, на которой он присутствует (Login.aspx) не звонит OnLoggedIn событие.

Точно так же, как Global.asax имеет глобальное уведомление о начале сеанса:

void Session_Start(object sender, EventArgs e) 
{
}

я предполагаю, что где-то есть уведомление о входе пользователя в систему:

void LoggedIn(object sender, EventArgs e)
{
}

Бонус Чтение

4 ответа

Решение

Я думаю, у вас нет уникального места для этого. В моем случае (MVC + log4net) я использую это:

  • В Global.asax Я проверяю аутентифицированных пользователей с помощью уже существующих файлов cookie.

    protected void Session_Start()
    {
        string ip = HttpContext.Current.Request.UserHostAddress;
    
        log.InfoFormat("Starting session: {0} from {1}.",Session.SessionID, ip);
    
        if ((HttpContext.Current != null) &&
            (HttpContext.Current.User != null) &&
            (HttpContext.Current.User.Identity.IsAuthenticated) )
        {
            string user = HttpContext.Current.User.Identity.Name;
            string type = "Cookie";
    
            log.InfoFormat("User {0} logged in with {1}.", user, type);
        }
    
    }
    
  • В моем контроллере аккаунта я проверяю локальные логины (я использую шаблон интернет-приложения из MVC4, но вы можете сделать это в своем Login.OnLoggedIn если вы используете веб-формы)

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult Login(LoginModel model, string returnUrl)
    {
        if (ModelState.IsValid && WebSecurity.Login(model.EMail, model.Password, persistCookie: model.RememberMe))
        {
            string user = model.EMail;
            string type = "Forms";
    
            log.InfoFormat("User {0} logged in with {1}.", user, type);
    
            return RedirectToLocal(returnUrl);
        }
    
        // If we got this far, something failed, redisplay form
        ModelState.AddModelError("", "The user name or password provided is incorrect.");
        log.ErrorFormat("Bad password or user name. User={0}", model.EMail, model.Password);
        return View(model);
    }
    
  • Но мне также нужно проверить наличие логинов OAuth, например:

    [AllowAnonymous]
    public ActionResult ExternalLoginCallback(string returnUrl)
    {
        AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
        if (!result.IsSuccessful)
        {
            log.Debug("External login failure.");
    
            return RedirectToAction("ExternalLoginFailure");
        }
    
        if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))
        {
            log.InfoFormat("User {0} logged in with External {1} login. External UserID = {2}",
                Membership.GetUser(OAuthWebSecurity.GetUserName(result.Provider, result.ProviderUserId)).UserName,
                result.Provider,
                result.ProviderUserId);
    
            return RedirectToLocal(returnUrl);
        }
    
        ...
    }
    

Вы можете сделать проверку на Application_AuthenticateRequest на global.asax - это место, где вы можете проверить, вошел ли запрос в систему или нет вместе с данными вашего сеанса, и решить, нужно ли инициализировать данные сеанса, как вы говорите.

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    string cookieName = FormsAuthentication.FormsCookieName;
    HttpCookie authCookie = Context.Request.Cookies[cookieName];

    //  check for logged in or not
    if (null != authCookie)
    {
        // is logged in... check if the session needs init

    }   
}

Или те же результаты с

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    //  check for logged in or not
    if(HttpContext.Current.User != null && 
        HttpContext.Current.User.Identity != null 
            && HttpContext.Current.User.Identity.IsAuthenticated)
    {
        // is logged in... check if the session needs init

    }   
}    

Вы можете назвать свой код в этих двух местах: OnLoggedIn событие из Login контроль, а также когда начинается сессия (используя Session_Start событие в вашем Global.asax), так как это будет первый запрос с данными пользователя. Там вы можете проверить, вошел ли пользователь в систему и, если да, сделать то, что вам нужно.

Хотя технически вход в систему идентичен аутентификации, у меня другая ментальная модель этого.

На мой взгляд, три следующие вещи являются отдельными вопросами:

  • Пользователь имеет / получает сеанс
  • Пользователь аутентифицирован
  • Пользователь вошел в систему

Для меня последнее из этих средств означает: "Для пользователя создан сеанс, пользователь прошел проверку подлинности, и сеанс был инициализирован для пользователя, прошедшего проверку".

Используя эту модель, пользователь может войти в систему, когда:

  • Пользователь входит в систему на странице входа в систему, и существующий сеанс инициализируется необходимыми данными пользователя.
  • Пользователь, прошедший предварительную проверку подлинности, заходит на сайт, и для него / нее создается и инициализируется новый сеанс

Точно так же пользователь выходит из системы, когда его / ее инициализированный сеанс уничтожен.

Использование этой модели будет означать:

  • Вы можете определить, когда пользователь "входит в систему" либо в Login.OnLoggedIn событие или Session_Start событие в Global.asax, Конечно, событие запуска сеанса также запускается для неаутентифицированных пользователей, поэтому вам нужно убедиться, что пользователь прошел аутентификацию при возникновении события.
  • Вы можете достаточно надежно сказать, когда пользователь "выходит из системы", либо явно выходя из системы, либо когда правильно инициализированный сеанс прерывается в Session_End событие в Global.asax. Я говорю достаточно надежно, потому что я думаю, что событие (-я) Session_End не обязательно будет запускаться, когда пул приложений перезапускается или умирает в случае сбоя. Хотя я не проверял это, поэтому я могу ошибаться.
  • Пользователь может быть одновременно "авторизован" несколько раз. По крайней мере, в IE вы можете начать "Новый сеанс" из меню "Файл". Это запускает новый IE, который не разделяет сеансовые куки с любыми существующими окнами IE. Это означает, что новый сеанс будет создаваться сервером, когда пользователь заходит на сайт, и в зависимости от используемого механизма аутентификации это может означать, что ему / ей также придется снова проходить аутентификацию.

Это не позволит вам "вывестисписок всех зарегистрированных пользователей" из коробки. Я думаю, вам нужно будет придумать способ самому отслеживать это. Это может мне более или менее сложно сделать. Особенно в том случае, когда ваше приложение работает в какой-то среде с балансировкой нагрузки, получить список всех текущих пользователей может быть сложно.

Другие вопросы по тегам