Jsp 如何在浏览器选项卡中区分会话?
在使用JSP和servlet用java实现的web应用程序中;如果我在用户会话中存储信息,则该信息将从同一浏览器的所有选项卡共享。如何在浏览器选项卡中区分会话? 在本例中:Jsp 如何在浏览器选项卡中区分会话?,jsp,servlets,browser,web-applications,sessionid,Jsp,Servlets,Browser,Web Applications,Sessionid,在使用JSP和servlet用java实现的web应用程序中;如果我在用户会话中存储信息,则该信息将从同一浏览器的所有选项卡共享。如何在浏览器选项卡中区分会话? 在本例中: <%@page language="java"%> <% String user = request.getParameter("user"); user = (user == null ? (String)session.getAttribute("SESSIONS_USER") : user); ses
<%@page language="java"%>
<%
String user = request.getParameter("user");
user = (user == null ? (String)session.getAttribute("SESSIONS_USER") : user);
session.setAttribute("SESSIONS_USER",user);
%>
<html><head></head><body>
<%=user %>
<form method="post">
User:<input name="user" value="">
<input type="submit" value="send">
</form>
</body></html>
用户:
将此代码复制到jsp页面(testpage.jsp
),在服务器上的web应用程序的现有上下文中部署此文件(我使用Apache Tomcat),然后使用正确的URL(localhost/context1/testpage.jsp
)打开浏览器(FF、IE7或Opera),在输入中键入您的姓名并提交表单。然后在同一浏览器中打开一个新选项卡,然后您可以在新选项卡上看到您的姓名(从会话中获取)。小心浏览器缓存,有时它似乎没有发生,但它在缓存中,请刷新第二个选项卡
谢谢。当从单个页面开始时,您可以使用链接重写将唯一标识符附加到所有URL(例如index.html/jsp/任何内容)。浏览器将为您的所有选项卡使用相同的cookie,因此您在cookie中放置的所有内容都不会是唯一的。您不应该这样做。如果您想这样做,您需要通过动态写入URL来强制用户使用应用程序的单个实例,使用类似的sessionID(而不是sessionID,它不会工作)id并在每个URL中传递它
我不知道您为什么需要它,但除非您需要制作一个完全不可用的应用程序,否则不要这样做。您必须意识到服务器端会话是HTTP的人工附加组件。由于HTTP是无状态的,服务器需要以某种方式识别请求属于它知道的特定用户,并且有一个会话。有两种方法可以做到这一点:
- 饼干。这是一种更干净、更流行的方法,但这意味着所有浏览器选项卡和窗口都由一个用户共享会话——事实上,这是可取的,而且我会对一个让我登录每个新选项卡的网站感到非常恼火,因为我非常频繁地使用选项卡
- URL重写。站点上的任何URL都附加了会话ID。这是更多的工作(你必须在你有站点内部链接的任何地方做一些事情),但是可以在不同的选项卡中有单独的会话,尽管通过链接打开的选项卡仍然会共享会话。这也意味着用户在访问您的站点时必须始终登录
对于测试,可以找到其他解决方案(例如在单独的VM上运行多个浏览器实例)。如果一个用户需要同时扮演不同的角色,那么应该在应用程序中处理“角色”概念,以便一个登录可以有多个角色。你必须决定这是使用URL重写,还是仅仅适应当前的情况更容易接受,因为用基于cookie的会话单独处理浏览器选项卡是不可能的。我提出了一个新的解决方案,它有一点开销,但似乎作为一个原型正在工作。一个假设是,您正在一个荣誉系统环境中登录,尽管这可以通过在切换选项卡时重新请求密码来调整 使用localStorage(或等效工具)和HTML5存储事件来检测新浏览器选项卡何时切换了哪个用户处于活动状态。出现这种情况时,创建一个重影覆盖,并显示一条消息,说明您无法使用当前窗口(或者暂时禁用该窗口,您可能不希望它如此显眼)。当窗口恢复焦点时,发送一个AJAX请求,将用户重新登录 这种方法的一个警告是:在没有焦点的窗口中(例如,如果延迟后发生调用),您不能进行任何正常的AJAX调用(即依赖于您的会话的调用),除非在此之前手动进行AJAX重新登录调用。所以实际上,您需要做的就是首先检查AJAX函数,以确保localStorage.Current_logged_in_user_id==window.yourAppNameSpace.user_id,如果没有,则首先通过AJAX登录 另一个是竞争条件:如果你切换窗口的速度足够快,以致于混淆了它,你可能会得到一个relogin1->relogin2->ajax1->ajax2序列,而ajax1是在错误的会话下进行的。解决方法是将登录AJAX请求推送到阵列上,然后在存储上,在发出新的登录请求之前,中止所有当前请求 最后一个要注意的问题是窗口刷新。如果有人在AJAX登录请求处于活动状态但尚未完成时刷新窗口,那么将以错误的人的名义刷新窗口。在这种情况下,您可以使用非标准beforeunload事件来警告用户潜在的混淆,并要求他们单击Cancel,同时重新发出AJAX登录请求。然后,他们唯一可以搞糟它的方法是在请求完成之前单击OK(或者意外地点击enter/spacebar,因为OK是——不幸的是在这种情况下——默认设置)。还有其他方法来处理这种情况,比如检测F5和Ctrl+R/Alt+R按下,这在大多数情况下都有效,但可能会被用户键盘快捷键重新配置或替代操作系统的使用所阻碍。然而,这在现实中是一种边缘情况,最坏的情况从来没有那么糟糕:在荣誉系统配置中,您将以错误的身份登录(但您可以通过使用颜色、样式、突出显示的名称等对页面进行个性化设置,使情况变得明显);在密码配置中,责任在于最后一个输入密码以注销或共享会话的人,或者如果此人实际上是当前用户,则不存在违规行为 但最终,每个选项卡应用程序只有一个用户(希望如此),该应用程序只需按其应该的方式运行,而不必设置概要文件,使用I
//Events
$(window).ready(function() {generateWindowID()});
$(window).focus(function() {setAppId()});
$(window).mouseover(function() {setAppId()});
function generateWindowID()
{
//first see if the name is already set, if not, set it.
if (se_appframe().name.indexOf("SEAppId") == -1){
"window.name = 'SEAppId' + (new Date()).getTime()
}
setAppId()
}
function setAppId()
{
//generate the cookie
strCookie = 'seAppId=' + se_appframe().name + ';';
strCookie += ' path=/';
if (window.location.protocol.toLowerCase() == 'https:'){
strCookie += ' secure;';
}
document.cookie = strCookie;
}
//variable name
string varname = "";
HttpCookie aCookie = Request.Cookies["seAppId"];
if(aCookie != null) {
varname = Request.Cookies["seAppId"].Value + "_";
}
varname += "_mySessionVariable";
//write session data
Session[varname] = "ABC123";
//readsession data
String myVariable = Session[varname];
How to differ sessions in browser-tabs?
23423.abc.com
242234.abc.com
235643.abc.com
<form method="post" action="/handler">
<input type="hidden" name="sessionId" value="123456890123456890ABCDEF01" />
<input type="hidden" name="action" value="" />
</form>
<input type="hidden" name="action" value="completeCheckout" />
<input type="hidden" name="data" value='{ "cardNumber" : "4111111111111111", ... ' />
var deferred = $q.defer(),
self = this,
onConnect = function(status){
if (status === Strophe.Status.CONNECTING) {
deferred.notify({status: 'connecting'});
} else if (status === Strophe.Status.CONNFAIL) {
self.connected = false;
deferred.notify({status: 'fail'});
} else if (status === Strophe.Status.DISCONNECTING) {
deferred.notify({status: 'disconnecting'});
} else if (status === Strophe.Status.DISCONNECTED) {
self.connected = false;
deferred.notify({status: 'disconnected'});
} else if (status === Strophe.Status.CONNECTED) {
self.connection.send($pres().tree());
self.connected = true;
deferred.resolve({status: 'connected'});
} else if (status === Strophe.Status.ATTACHED) {
deferred.resolve({status: 'attached'});
self.connected = true;
}
},
output = function(data){
if (self.connected){
var rid = $(data).attr('rid'),
sid = $(data).attr('sid'),
storage = {};
if (localStorageService.cookie.get('day_bind')){
storage = localStorageService.cookie.get('day_bind');
}else{
storage = {};
}
storage[$window.name] = sid + '-' + rid;
localStorageService.cookie.set('day_bind', angular.toJson(storage));
}
};
if ($window.name){
var storage = localStorageService.cookie.get('day_bind'),
value = storage[$window.name].split('-')
sid = value[0],
rid = value[1];
self.connection = new Strophe.Connection(BoshService);
self.connection.xmlOutput = output;
self.connection.attach('bosh@' + BoshDomain + '/' + $window.name, sid, parseInt(rid, 10) + 1, onConnect);
}else{
$window.name = 'web_' + (new Date()).getTime();
self.connection = new Strophe.Connection(BoshService);
self.connection.xmlOutput = output;
self.connection.connect('bosh@' + BoshDomain + '/' + $window.name, '123456', onConnect);
}