Советы по отслеживанию пользователей "Last Ip Address" - PullRequest
1 голос
/ 06 мая 2011

Прежде всего, это не вопрос , как получить IP-адрес пользователя , поскольку я знаю, как это сделать.

В основном, администраторымоего веб-сайта (веб-приложение ASP.NET MVC 3) нужна возможность заблокировать определенный IP-адрес от отправки пользовательского контента.Поэтому я храню «IP-адрес» против пользователя в нашей системе.Круто.

Мой вопрос:

Когда (например, в какое время события жизненного цикла страницы) я должен проверять текущий IP-адрес пользователя и сохранять его в базе данных?

В данный момент я думаю об использовании сеанса .То есть, когда я впервые создаю сеанс (например, Session_OnStart()), возьмите IP-адрес пользователя и вставьте его в сеанс.Затем, когда сессия заканчивается (например, Session_OnEnd()), я вижу, отличается ли IP-адрес в сессии от адреса базы данных.Если это так, обновите БД.

В настоящее время мы используем InProc , но есть большой шанс, что мы позже перейдем к StateServer - и состояниям MSDN Session_OnEnd доступно только для InProc .Так что это может быть проблемой.

Есть какие-нибудь мысли / альтернативы этому подходу?

РЕДАКТИРОВАТЬ

Поэтому я попытался использовать Session_OnStart(), чтобы попытатьсявыполните следующие действия:

Если пользователь прошел проверку подлинности, получите его IP-адрес, последний IP-адрес из базы данных и, если они другие, обновите базу данных.

Но проблема, похоже, заключается в том, что Session_OnStart запускается до Application_AuthenticateRequest - поэтому он никогда не проходит проверку "аутентифицировано".

Хороший пример, если пользователь заходит на мой сайт- используя Forms Auth, который устанавливает cookie с датой истечения срока недели (например).

Затем они возвращаются через несколько дней - Session_OnStart запускается - но они еще не аутентифицированы,Несмотря на то, что файл cookie присутствует - он еще не был обработан в контексте http.

Таким образом, Session_OnStart выглядит бесполезным - есть другие идеи?

Ответы [ 4 ]

1 голос
/ 09 мая 2011

Принял ответ @ lomaxx - но подумал, что добавлю свой собственный для других и рассуждения о том, почему это необходимо.

Решение : фильтр глобальных действий, выполняющийся при каждом запросе.

(упрощенный) код:

public class UserTrackingFilterAttribute : ActionFilterAttribute
{
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        // If the user isn't authenticated or we have already tracked IP this session, bubble back up to base context.
        if (!Authenticated || HaveTrackedIpAddressThisSession)
        {
            base.OnResultExecuted(filterContext);
            return;
        }

        // Get the users current ip address.
        var currentIp = HttpContext.Current.Request.CurrentIpAddress(); // extension method to read server variables, cater for proxy, etc

        // Get the users last known ip address from repository.
        var userService = ObjectFactory.GetInstance(typeof(IUserService)) as IUserService;
        var unitOfWork = ObjectFactory.GetInstance(typeof(IUnitOfWork)) as IUnitOfWork;
        if (userService == null || unitOfWork == null) return;

        // See if the user's ip has changed.
        var currentUser = userService.FindById(CurrentUserId);
        if (currentUser == null || (currentUser.LastIpAddress != null && IPAddress.Parse(currentUser.LastIpAddress).Equals(currentIp)))
        {
            // User cannot be found or IP hasn't changed - set session key and bubble back up to base context.
            HaveTrackedIpAddressThisSession = true;
            base.OnResultExecuted(filterContext);
            return;
        }

        // User's ip has changed - update ip address.
        currentUser.LastIpAddress = currentIp.ToString();

        // Save.
        userService.Save(currentUser);

        // Commit.
        unitOfWork.Commit();

        // Update session key.
        HaveTrackedIpAddressThisSession = true;
    }
}

«CurrentUserId» и «HaveTrackedIpAddressThisSession» являются частными свойствами для сокращения кода в этом методе.В основном они читают HttpContext.Current.User.Identity и HttpContext.Current.Session["someKey"] соответственно.

Зачем мне нужен глобальный фильтр действий над событием Global.asax: , поскольку моя логика требует присутствия субъекта Http, я могуне использовать Session_OnStart, поскольку в то время cookie-файл проверки подлинности форм не был расшифрован в основной идентификатор.Таким образом, хотя это выполняется при каждом запросе страницы, «флаг» сеанса уменьшает эти издержки.

1 голос
/ 06 мая 2011

Будет ли проблема в том, чтобы просто зарегистрировать ip в начале сеанса, а не в конце?Как вы говорите, ip не изменится во время сеанса.

0 голосов
/ 06 мая 2011

Я предполагаю, что вы проводите сравнение в базе данных, читая ваш вопрос.

Мое предложение - сохранить блок-лист в web.config для простоты и сравнивать входящий идентификатор с ним всякий раз, когда вам нужно..

Если вам нужно сохранить список блоков в базе данных, я бы сказал, используйте класс кэширования для кэширования списка блоков в течение разумного промежутка времени и сравните ip с списком блоков в вашем коде, а не в базе данных..

0 голосов
/ 06 мая 2011

Поскольку это asp.net MVC, и вы хотите, чтобы он выполнялся для всех запросов, я хотел бы рассмотреть возможность использования фильтра глобальных действий, подобного описанному здесь http://weblogs.asp.net/gunnarpeipman/archive/2010/08/15/asp-net-mvc-3-global-action-filters.aspx

...