Как запретить нескольким окнам обозревателя поделиться одним и тем же сеансом в asp.net

У меня есть приложение ASP.net, которое в основном представляет собой экран ввода данных для процесса физического осмотра. Пользователи хотят иметь возможность открывать несколько окон браузера и одновременно вводить данные из нескольких проверок. Сначала я использовал сеансы на основе файлов cookie, и, очевидно, это взорвалось.

Я переключился на использование сеансов без файлов cookie, в которых хранится сеанс в URL-адресе, и при тестировании это, похоже, решило проблему. Каждое окно/вкладка браузера имело другой идентификатор сеанса, а данные, введенные в один, не содержали данных clobber, введенных в другом.

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

Помимо того, что они не сообщают, что они не копируют и не вставляют, или не убеждают их только вводить один за раз, как я могу предотвратить эту ситуацию?

Ответы

Ответ 1

Подумайте об использовании ViewState вместо Session, поскольку ViewState отображает информацию о состоянии клиенту (HTML-страница). Я не уверен, что когда-нибудь сможете получить подробный контроль над поведением браузера, потому что идентификатор сеанса поддерживается браузером так, как это сделал производитель. Таким образом, ViewState более предсказуем не только, но и для будущих версий браузера.

Ответ 2

Это очень хороший вопрос, о котором я тоже долго думал и думал.

Храните основную веб-страницу в iframe. Имейте javascript, чтобы проверить, находится ли ваша веб-страница в родительском iframe. Если нет, то они открыли несколько окон браузера.

Вам нужно убедиться, что все ваше приложение является дружественным iframe.

Ответ 3

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

Веб-приложение (и страницы) должно обрабатывать несколько процессов проверки в рамках одного сеанса пользователя.

Независимо от того, какие данные, которые хранятся в переменных сеанса, не должны быть явно открыты для сингулярной обработки. Они должны храниться в коллекциях, которые легко идентифицируют, какой набор данных принадлежит процессу проверки. Каждое представление страницы обратно на веб-сервер должно содержать идентификатор, к которому относится процесс проверки, так что правильный набор сеансов можно согласовать и вытащить для использования.

концепция псевдокода

var inspectionID = this.inspectionLabel.Text;
var inspectionSets = (Hashtable)Session["inspections"];
var inspection = (Inspection)inspectionSets[inspectionID];

Ответ 4

Должны ли пользователи войти в систему с разными учетными записями для доступа к различным физическим проверкам? Мне кажется, что пока PhysicalInspectionID является частью URL-адреса, тогда не должно быть никаких проблем при одновременном редактировании нескольких физических проверок.

Например,

http://inspections.mydomain.com/edit/23

Конечно, если они копируют URL-адрес, они получат дубликат другого окна, но это научит их не делать этого. Вместо этого они открывают другое окно и просматривают соответствующий контроль (или добавляют новый) через пользовательский интерфейс.

Ответ 5

Решение этой проблемы может быть реализовано следующим образом:

public static class CommonHelper
{
   public static bool SiteGuard
    {
        get
        {
            if(HttpContext.Current.Session["SiteGuard"] == null)
               return true;
            return (bool)HttpContext.Current.Session["SiteGuard"];
        }
        set
        {
            HttpContext.Current.Session["SiteGuard"] = value;
        }
    }
}

public partial class TestPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if(!Page.IsPostBack)
        {
            bool go = false;
            for(int i = 0; i < 50; i++) // wait for the service to work (5 secs max)
            {
                if(CommonHelper.SiteGuard)
                {
                   go = true;
                   break;
                }
                Thread.Sleep(100);
            }
            if(!go)
               Response.Redirect("Login.aspx");

            SiteGuard = false; // from now on, nobody can visit your site
        }
        // Now as long as Page.IsPostBack is true you are in a good shape
    }
}

Добавьте веб-службу asmx (или любой другой тип услуг, который, по вашему мнению, подходит) в ваш корневой проект и добавьте к нему следующий метод:

    [WebMethod(EnableSession = true)]
    public void FreeSiteGuard()
    {
        HttpContext.Current.Session["SiteGuard"] = null;
    }

На главной странице или на каждой странице добавьте следующий javascript:

<script type="text/javascript">
    window.onbeforeunload = function (e) {
        e = e || window.event;
        if (e) {
            // Invoke web service 
           YourProject.YourWebServiceName.FreeSiteGuard();
        }
    };
</script>

Обратите внимание, что время отклика вашего сайта зависит от скорости веб-службы.

Ответ 6

Это то, что я использую в ASP.NET MVC, чтобы запретить аутентифицированным пользователям открывать несколько вкладок:

<script language="javascript" type="text/javascript">
    @if(Request.IsAuthenticated)
    {
        <text>
        if (window.name != 'singleWindow') {
            window.location.href = "Content/ErrorPages/SingleTab.htm";
        } 
        </text>
    }
    else
    {
        <text>
        window.name = "singleWindow";
        </text>
    }
</script>

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

Две проблемы:

  • не работает, если отключен JavaScript.
  • если по ошибке пользователь закрывает исходную вкладку, а затем вставляет некоторую другую ссылку на мой сайт в адресной строке, пользователь всегда будет получать страницу с ошибкой. Чтобы дать пользователю возможность восстановления, я включил ссылку "Выход" на странице SingleTab.htm, чтобы пользователь мог уничтожить его cookie сеанса и начать новый сеанс.

Ответ 7

Создайте новый sessionId, если в запросе нет ссылки. Это решает проблему URL-адреса для копирования-вставки. Сохраните sessionId в URL-адресе, как и вы.