Как запретить нескольким окнам обозревателя поделиться одним и тем же сеансом в 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-адресе, как и вы.