เซสชันต่างๆในแท็บเบราว์เซอร์ต่างกันอย่างไร


136

ในเว็บแอปพลิเคชันที่ใช้งานใน java โดยใช้ JSP และ Servlets หากฉันเก็บข้อมูลในเซสชันผู้ใช้ข้อมูลนี้จะแชร์จากแท็บทั้งหมดจากเบราว์เซอร์เดียวกัน เซสชันต่างๆในแท็บเบราว์เซอร์ต่างกันอย่างไร ในตัวอย่างนี้:

<%@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) ปรับใช้ไฟล์นี้ในบริบทที่มีอยู่ของเว็บแอปพลิเคชันบนเซิร์ฟเวอร์ (ฉันใช้ Apache Tomcat) จากนั้นเปิดเบราว์เซอร์ (FF, IE7 หรือ Opera) โดยใช้ URL ที่ถูกต้อง ( localhost/context1/testpage.jsp) พิมพ์ ชื่อของคุณในการป้อนข้อมูลและส่งแบบฟอร์ม จากนั้นเปิดแท็บใหม่ในเบราว์เซอร์เดียวกันจากนั้นคุณจะเห็นชื่อของคุณ (รับจากเซสชัน) บนแท็บใหม่ ระวังเบราว์เซอร์แคชบางครั้งดูเหมือนว่าจะไม่เกิดขึ้น แต่อยู่ในแคชรีเฟรชแท็บที่สอง

ขอบคุณ.


ที่เกี่ยวข้อง: stackoverflow.com/questions/4479995/…
Bozho

1
นี่คือสิ่งที่ผู้ใช้ต้องทำ: เปิด IE คลิกที่ "File-> New Session"
Stefan Steiger

3
@Quandary โซลูชันของคุณไม่ใช่โซลูชันทั่วไป (ในเบราว์เซอร์อื่นไม่ทำงาน) และที่สำคัญที่สุดคือไม่เป็นมิตรกับผู้ใช้ (ผู้ใช้ไม่รู้เกี่ยวกับเซสชัน)
Oriol Terradas

2
บางคนดูเหมือนนึกไม่ออกว่าจุดประสงค์ของสิ่งนี้คืออะไร โดเมนปัญหาส่วนใหญ่เป็นสถานการณ์ใด ๆ ที่คุณต้องการอนุญาต "มุมมอง" ที่แตกต่างกันของเว็บไซต์ของคุณ เมื่อผู้ใช้สามารถดูเว็บไซต์ของคุณได้มากกว่าหนึ่งครั้งพวกเขาก็ต้องใช้เวลานาน (หรือพยายามโดยไม่ตั้งใจ) อย่างหลีกเลี่ยงไม่ได้ในการเข้าถึงสองมุมมองที่แตกต่างกันในเวลาเดียวกัน ตัวอย่าง ได้แก่ : การกำหนดเวอร์ชันชั่วคราว (เปลี่ยนไปใช้การดูเว็บไซต์ตามที่เคยมีมาในอดีต); แซนด์บ็อกซ์ (ทำการเปลี่ยนแปลงเว็บไซต์ที่คนอื่นยังมองไม่เห็น); มุมมองตามบทบาท (ดูว่าเว็บไซต์มีลักษณะอย่างไรสำหรับผู้ใช้ที่ด้อยโอกาส) ฯลฯ
Ron Burk

คำตอบ:


92

คุณสามารถใช้ HTML5 SessionStorage (window.sessionStorage) คุณจะสร้างรหัสสุ่มและบันทึกในพื้นที่เก็บข้อมูลเซสชันต่อแท็บเบราว์เซอร์ จากนั้นแต่ละแท็บของเบราว์เซอร์จะมี Id ของตัวเอง

ข้อมูลที่จัดเก็บโดยใช้ sessionStorage จะไม่คงอยู่ในแท็บเบราว์เซอร์แม้ว่าสองแท็บทั้งสองจะมีหน้าเว็บจากต้นทางโดเมนเดียวกันก็ตาม กล่าวอีกนัยหนึ่งข้อมูลภายใน sessionStorage ไม่ได้ จำกัด อยู่แค่โดเมนและไดเร็กทอรีของเพจที่เรียกใช้ แต่แท็บเบราว์เซอร์ที่มีเพจอยู่ตรงกันข้ามกับคุกกี้เซสชันซึ่งจะมีข้อมูลจากแท็บหนึ่งไปอีกแท็บ


7
จากเอกสาร: "ข้อมูลที่จัดเก็บโดยใช้ sessionStorage จะไม่คงอยู่ในแท็บเบราว์เซอร์แม้ว่าสองแท็บทั้งสองจะมีหน้าเว็บที่มาจากโดเมนเดียวกันกล่าวอีกนัยหนึ่งข้อมูลภายใน sessionStorage ไม่ได้ จำกัด เฉพาะโดเมนและไดเร็กทอรีของเพจที่เรียกใช้ แต่ แท็บเบราว์เซอร์ที่มีเพจอยู่ตรงกันข้ามกับคุกกี้เซสชันซึ่งจะคงข้อมูลจากแท็บหนึ่งไปอีกแท็บ " การทดสอบอย่างง่ายช่วยยืนยันพฤติกรรมนี้ใน Chrome และ FF
jswanson

21
หมายเหตุรหัสนี้จะซ้ำกันเมื่อใช้คุณลักษณะ "แท็บซ้ำ" ของ Chrome โดยทั่วไปสิ่งนี้ไม่ใช่ปัญหา แต่ควรพิจารณาให้ดี
JosiahDaniels

ยกเว้นเมื่อคุณ "ทำซ้ำ" แท็บใน Chrome หรือ Firefox ในกรณีนี้ SessionStorage จะถูกคัดลอก
Tiago Freitas Leal

@Gonzalo Gallotti: และจะช่วยฉันได้อย่างไรถ้าเซสชันเป็นฝั่งเซิร์ฟเวอร์ )))
Stefan Steiger

@StefanSteiger. จากนั้นคุณสามารถส่งรหัส BrowserTab (บันทึกไว้ใน Session Storage) ด้วย Ajax Call ของคุณ ในฝั่งเซิร์ฟเวอร์คุณจะต้องใช้ตรรกะที่กำหนดเองเนื่องจาก WebSession เหมือนกัน แต่คุณสามารถสร้าง HashMap ด้วยวัตถุเซสชันตามแท็บ
Gonzalo Gallotti

24

คุณต้องตระหนักว่าเซสชันฝั่งเซิร์ฟเวอร์เป็นส่วนเสริมเทียมของ HTTP เนื่องจาก HTTP ไม่มีสถานะเซิร์ฟเวอร์จึงจำเป็นต้องรับรู้ว่าคำขอเป็นของผู้ใช้เฉพาะที่ตนรู้จักและมีเซสชัน มี 2 ​​วิธีในการดำเนินการนี้:

  • คุ้กกี้. วิธีที่สะอาดและเป็นที่นิยมมากขึ้น แต่หมายความว่าแท็บและหน้าต่างเบราว์เซอร์ทั้งหมดโดยผู้ใช้คนเดียวแชร์เซสชัน - IMO นี่เป็นสิ่งที่พึงปรารถนาและฉันจะรู้สึกรำคาญมากที่ไซต์ที่ทำให้ฉันเข้าสู่ระบบสำหรับแต่ละแท็บใหม่เนื่องจากฉัน ใช้แท็บอย่างเข้มข้น
  • การเขียน URL ใหม่ URL ใด ๆ บนไซต์มีรหัสเซสชันต่อท้าย วิธีนี้ใช้ได้ผลมากกว่า (คุณต้องทำบางอย่างทุกที่ที่มีลิงก์ภายในไซต์) แต่ทำให้สามารถแยกเซสชันในแท็บต่างๆได้แม้ว่าแท็บที่เปิดผ่านลิงก์จะยังคงแชร์เซสชัน นอกจากนี้ยังหมายความว่าผู้ใช้จะต้องเข้าสู่ระบบเสมอเมื่อเขามาที่ไซต์ของคุณ

คุณพยายามทำอะไรต่อไป? ทำไมคุณถึงต้องการให้แท็บมีเซสชันแยกกัน อาจมีวิธีที่จะบรรลุเป้าหมายโดยไม่ต้องใช้เซสชันเลย?

แก้ไข: สำหรับการทดสอบสามารถพบโซลูชันอื่น ๆ (เช่นการเรียกใช้อินสแตนซ์เบราว์เซอร์หลายตัวบน VM แยกกัน) หากผู้ใช้รายหนึ่งจำเป็นต้องแสดงบทบาทที่แตกต่างกันในเวลาเดียวกันแนวคิด "บทบาท" ควรได้รับการจัดการในแอปเพื่อให้การเข้าสู่ระบบหนึ่งครั้งมีหลายบทบาท คุณจะต้องตัดสินใจว่าการใช้การเขียน URL ใหม่หรือการดำเนินชีวิตตามสถานการณ์ปัจจุบันเป็นสิ่งที่ยอมรับได้มากกว่าเพราะเป็นไปไม่ได้ที่จะจัดการแท็บเบราว์เซอร์แยกกันกับเซสชันที่ใช้คุกกี้


6
สำหรับแอปพลิเคชันขนาดใหญ่ที่เก็บข้อมูลผู้ใช้และสภาพแวดล้อม เมื่อมีคนเข้าสู่ระบบด้วยผู้ใช้ที่แตกต่างกันในแท็บที่แตกต่างกันเพื่อทดสอบหรือสำหรับบทบาทที่แตกต่างเขาจะข้ามข้อมูลจากแท็บ
Oriol Terradas

เป็นเพียงส่วนเสริมที่ล่าช้ามากว่าทำไม: เพราะฉันจำเป็นต้องรู้สิ่งนี้เพื่อที่จะรู้ว่าหน้าใดในไซต์ของฉันเช่นผู้ใช้มุ่งเน้นไปที่ผู้ใช้และไม่ใช่แค่พวกเขาไปจากหน้าหนึ่งไปอีกหน้าหนึ่ง ( แทนที่จะเปลี่ยนจากแท็บหนึ่งไปอีกแท็บ)
Oliver Williams

16

คุณสมบัติ window.name Javascript เป็นสิ่งเดียวที่จะคงอยู่ในกิจกรรมของแท็บ แต่ยังคงเป็นอิสระได้ (แทน URL guff)


3
window.sessionStorage ก็เช่นกัน
felickz

3
ระวังเนื่องจากพื้นที่เก็บข้อมูลเซสชันจะถูกคัดลอกไปยังแท็บใหม่เมื่อผู้ใช้เลือก "เปิดในแท็บใหม่" ... หวังว่าฉันจะมีลิงค์สำหรับรายละเอียด แต่โปรดดู: bugzilla.mozilla.org/show_bug.cgi?id=818389
felickz

2
โปรดทราบว่าสิ่งที่คุณบันทึกไว้ในการตั้งค่า window.name จะยังสามารถใช้ได้ในโดเมนอื่นเมื่อผู้ใช้เปลี่ยนไปยังหน้าอื่น ๆ ในแท็บเดียวกัน
nakib

15

คุณไม่ควร หากคุณต้องการทำสิ่งนั้นคุณจำเป็นต้องบังคับให้ผู้ใช้ใช้อินสแตนซ์เดียวของแอปพลิเคชันของคุณโดยการเขียน URL ทันทีให้ใช้รหัสเซสชันเหมือนกัน (ไม่ใช่ sessionid จะใช้ไม่ได้) และส่งผ่านในทุก URL

ฉันไม่รู้ว่าทำไมคุณถึงต้องการ แต่ถ้าคุณไม่จำเป็นต้องสร้างแอปพลิเคชันที่ใช้ไม่ได้โดยสิ้นเชิงอย่าทำ


9
สำหรับแอปพลิเคชันขนาดใหญ่ที่เก็บข้อมูลผู้ใช้และสภาพแวดล้อม เมื่อมีคนเข้าสู่ระบบด้วยผู้ใช้ที่แตกต่างกันในแท็บที่แตกต่างกันเพื่อทดสอบหรือสำหรับบทบาทที่แตกต่างเขาจะข้ามข้อมูลจากแท็บ
Oriol Terradas

39
คำตอบเก่าฉันรู้ แต่อีเมลของ Google อนุญาตให้คุณมีบัญชีที่แตกต่างกันต่อแท็บและไม่ใช่ "แอปพลิเคชันที่ใช้ไม่ได้ทั้งหมด"
จอร์จ

2
@ George คำตอบยังคงถูกต้องและสำหรับตัวอย่างของคุณคุณจะเห็นในหมายเลข url แสดงถึงดัชนีของบัญชีที่จัดเก็บในคุกกี้ google mail เป็นเพียงการจัดเก็บคุกกี้ทั้งหมดและเลือกหนึ่งรายการตาม url
Mhmd

6
ไม่แน่ใจว่าคำตอบยังถูกต้องคุณสามารถทำได้อย่างชัดเจน Gmail ทำได้ ถึงอย่างไรมันอาจจะไม่สวยหรู แต่ได้ผลและนั่นคือสิ่งที่สำคัญ
จอร์จ

2
คำตอบเก่า แต่ฉันอาจเพิ่มว่า Whatsapp และ Telegram ไม่อนุญาตให้คุณเปิดสองแท็บในเวลาเดียวกัน สิ่งนี้ไม่ได้ทำให้ใช้ไม่ได้
Charlie

13

ฉันได้พบกับโซลูชันใหม่ซึ่งมีค่าใช้จ่ายเล็กน้อย แต่ดูเหมือนว่าจะใช้งานได้จนถึงต้นแบบ ข้อสันนิษฐานอย่างหนึ่งคือคุณอยู่ในสภาพแวดล้อมของระบบที่มีเกียรติสำหรับการเข้าสู่ระบบแม้ว่าจะสามารถปรับเปลี่ยนได้โดยการขอรหัสผ่านใหม่ทุกครั้งที่คุณเปลี่ยนแท็บ

ใช้ localStorage (หรือเทียบเท่า) และเหตุการณ์หน่วยเก็บข้อมูล HTML5 เพื่อตรวจจับเมื่อแท็บเบราว์เซอร์ใหม่เปลี่ยนผู้ใช้ที่ใช้งานอยู่ เมื่อเป็นเช่นนั้นให้สร้างภาพซ้อนทับพร้อมข้อความแจ้งว่าคุณไม่สามารถใช้หน้าต่างปัจจุบันได้ (หรือปิดใช้งานหน้าต่างชั่วคราวคุณอาจไม่ต้องการให้หน้าต่างนั้นเด่นชัด) เมื่อหน้าต่างกลับมาโฟกัสได้ให้ส่งบันทึกการร้องขอ AJAX ผู้ใช้กลับเข้ามา

ข้อแม้อย่างหนึ่งสำหรับแนวทางนี้: คุณไม่สามารถมีการเรียก AJAX ตามปกติ (เช่นการโทรที่ขึ้นอยู่กับเซสชันของคุณ) เกิดขึ้นในหน้าต่างที่ไม่มีโฟกัส (เช่นหากคุณมีสายเกิดขึ้นหลังจากเกิดความล่าช้า) เว้นแต่ คุณทำการโทรเข้าสู่ระบบอีกครั้ง AJAX ด้วยตนเองก่อนหน้านั้น ดังนั้นสิ่งที่คุณต้องทำจริงๆคือตรวจสอบฟังก์ชั่น AJAX ของคุณก่อนเพื่อให้แน่ใจว่า localStorage.currently_logged_in_user_id === window.yourAppNameSpace.user_id และหากไม่มีให้เข้าสู่ระบบก่อนผ่าน AJAX

อีกประการหนึ่งคือเงื่อนไขการแข่งขัน: หากคุณสามารถสลับ windows ได้เร็วพอที่จะสับสนคุณอาจจบลงด้วยการเข้าสู่ระบบใหม่ 1-> relogin2-> ajax1-> ajax2 ลำดับโดยที่ ajax1 ทำภายใต้เซสชันที่ไม่ถูกต้อง หลีกเลี่ยงสิ่งนี้โดยการพุชคำร้องขอ AJAX ล็อกอินไปยังอาร์เรย์จากนั้นบนที่เก็บข้อมูลและก่อนที่จะออกคำร้องขอล็อกอินใหม่ให้ยกเลิกคำร้องขอปัจจุบันทั้งหมด

gotcha สุดท้ายที่ต้องระวังคือการรีเฟรชหน้าต่าง หากมีคนรีเฟรชหน้าต่างในขณะที่คุณมีคำขอเข้าสู่ระบบ AJAX ที่ใช้งานอยู่ แต่ยังไม่เสร็จสมบูรณ์ระบบจะรีเฟรชในชื่อของบุคคลที่ไม่ถูกต้อง ในกรณีนี้คุณสามารถใช้เหตุการณ์ก่อนยกเลิกการโหลดที่ไม่เป็นมาตรฐานเพื่อเตือนผู้ใช้เกี่ยวกับมิกซ์อัพที่อาจเกิดขึ้นและขอให้พวกเขาคลิกยกเลิกในขณะที่ออกคำขอเข้าสู่ระบบ AJAX ใหม่ จากนั้นวิธีเดียวที่พวกเขาสามารถแก้ไขได้คือการคลิกตกลงก่อนที่คำขอจะเสร็จสมบูรณ์ (หรือโดยการกดปุ่ม Enter / spacebar โดยไม่ได้ตั้งใจเพราะตกลง - น่าเสียดายสำหรับกรณีนี้ - ค่าเริ่มต้น) มีวิธีอื่นในการจัดการกรณีนี้เช่น ตรวจจับการกด F5 และ Ctrl + R / Alt + R ซึ่งจะใช้งานได้ในกรณีส่วนใหญ่ แต่อาจถูกขัดขวางโดยการกำหนดค่าแป้นพิมพ์ลัดของผู้ใช้ใหม่หรือการใช้ระบบปฏิบัติการอื่น อย่างไรก็ตามนี่เป็นข้อได้เปรียบเล็กน้อยในความเป็นจริง และสถานการณ์ในกรณีที่เลวร้ายที่สุดก็ไม่เคยเลวร้าย: ในการกำหนดค่าระบบเกียรติยศคุณจะเข้าสู่ระบบในฐานะคนผิด (แต่คุณสามารถทำให้ชัดเจนได้ว่าเป็นกรณีนี้โดยการปรับแต่งเพจด้วยสีสไตล์ชื่อที่แสดงอย่างชัดเจน ฯลฯ ); ในการกำหนดค่ารหัสผ่านความรับผิดชอบจะอยู่ที่บุคคลสุดท้ายที่ป้อนรหัสผ่านเพื่อออกจากระบบหรือแชร์เซสชันของตนหรือหากบุคคลนี้เป็นผู้ใช้ปัจจุบันจริงก็จะไม่มีการละเมิด

แต่ในที่สุดคุณก็มีแอปพลิเคชันแบบหนึ่งผู้ใช้ต่อแท็บที่ (หวังว่า) จะทำหน้าที่ได้ตามที่ควรโดยไม่จำเป็นต้องตั้งค่าโปรไฟล์ใช้ IE หรือเขียน URL ใหม่ ตรวจสอบให้แน่ใจว่าคุณทำให้ชัดเจนในแต่ละแท็บที่ลงชื่อเข้าใช้แท็บนั้นแม้ว่า ...


6
+1 เพราะคุณใช้เวลาคิดเรื่องนี้จริงๆ! :-) ดูคำเตือนทั้งหมดคุณก็รู้ว่ามันเป็นความคิดที่ไม่ดี บทเรียนของฉันที่ได้เรียนรู้จากสิ่งนี้คือการเข้าใจอย่างแท้จริงว่าข้อมูลใดควรเข้าสู่เซสชันและข้อมูลใดไม่ควร
ปีเตอร์

10

เรามีปัญหานี้และเราแก้ไขได้ง่ายมาก ฉันหมายความว่าง่ายเพราะไม่มีการเขียนโปรแกรมที่เกี่ยวข้อง สิ่งที่เราต้องการทำคือให้ผู้ใช้ลงชื่อเข้าใช้หลายบัญชีภายในหน้าต่างเบราว์เซอร์เดียวกันโดยไม่ขัดแย้งกับเซสชัน

ดังนั้นการแก้ปัญหาคือโดเมนย่อยแบบสุ่ม

23423.abc.com
242234.abc.com
235643.abc.com

ดังนั้นเราจึงขอให้ผู้ดูแลระบบของเรากำหนดค่าใบรับรอง SSL สำหรับ * .abc.com แทน abc.com จากนั้นด้วยการเปลี่ยนแปลงรหัสเพียงเล็กน้อยทุกครั้งที่ผู้ใช้พยายามเข้าสู่ระบบเขาจะเข้าสู่ระบบในแท็บด้วยหมายเลขโดเมนย่อยแบบสุ่ม เพื่อให้แต่ละแท็บมีเซสชันของตัวเองอย่างอิสระ นอกจากนี้เพื่อหลีกเลี่ยงความขัดแย้งเราได้พัฒนาหมายเลขสุ่มโดยใช้แฮชหรือ md5 ของรหัสผู้ใช้


3
ดูเหมือนว่าจะเป็นทางเลือกที่ชาญฉลาดในการเขียน URL ใหม่ คุณลงเอยด้วยตัวแปรที่ต้องการ (รหัสเซสชัน) ในตำแหน่งที่สอดคล้องกับ HTTP ที่มองเห็นได้ แต่ไม่เกะกะ สิ่งที่ควรคำนึงถึง: 1) ต้องใช้สัญลักษณ์แทนบน DNS อย่างชัดเจน 2) ทั้งเว็บไซต์ของคุณต้องหลีกเลี่ยง URL ที่แน่นอนที่จะนำผู้ใช้กลับไปยัง (เช่น) โดเมนย่อย "www" 3) อาจต้องการป้องกันไม่ให้โปรแกรมรวบรวมข้อมูลเว็บ แต่นี่อาจเป็นสถานการณ์เว็บส่วนตัวซึ่งอาจทำได้แล้ว ขอบคุณสำหรับการแบ่งปัน!
รอนเบิร์

@ user3534653: ฉันชอบแนวทางนี้ แต่คุณบอกว่า "ไม่เกี่ยวข้องกับการเขียนโปรแกรม" จากนั้นให้คุณพูดว่า "มีการเปลี่ยนแปลงรหัสเล็กน้อย" จริงๆแล้วการเปลี่ยนโค้ดเพียงเล็กน้อยไม่ใช่การเขียนโปรแกรม? ;) นอกจากนี้วิธีนี้อาจใช้ไม่ได้หากคุณมีแอปพลิเคชันหลายตัวที่มีลิงก์ Canonical ซึ่งโดเมนเป็นฮาร์ดโค้ด / กำหนดค่า (ตามรูปแบบบัญญัติ)
Stefan Steiger

5

ฉันจะซื่อสัตย์ที่นี่ . . ทุกอย่างข้างต้นอาจจะหรืออาจไม่เป็นจริง แต่ทั้งหมดดูเหมือนWAYซับซ้อนเกินไปหรือไม่ทราบว่าสิ่งที่อยู่ในแท็บจะถูกฝั่งเซิร์ฟเวอร์ที่ใช้

บางครั้งเราต้องใช้มีดโกนของ Occam

นี่คือแนวทางของ Occam: (ไม่ฉันไม่ใช่ Occam เขาเสียชีวิตในปี 1347)

1) กำหนดรหัสเฉพาะของเบราว์เซอร์ให้กับเพจของคุณเมื่อโหลด . . เฉพาะในกรณีที่หน้าต่างยังไม่มี id (ให้ใช้คำนำหน้าและการตรวจจับ)

2) ในทุกหน้าที่คุณมี (ใช้ไฟล์ส่วนกลางหรือบางสิ่งบางอย่าง) เพียงแค่ใส่รหัสเพื่อตรวจจับเหตุการณ์โฟกัสและ / หรือเหตุการณ์ที่วางเมาส์เหนือ (ฉันจะใช้ jquery สำหรับส่วนนี้เพื่อความสะดวกในการเขียนโค้ด)

3) ในฟังก์ชั่นโฟกัส (และ / หรือเมาส์โอเวอร์) ของคุณให้ตั้งค่าคุกกี้ด้วย window.name ในนั้น

4) อ่านค่าคุกกี้จากฝั่งเซิร์ฟเวอร์ของคุณเมื่อคุณต้องการอ่าน / เขียนข้อมูลเฉพาะแท็บ

ด้านลูกค้า:

//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;
}

ฝั่งเซิร์ฟเวอร์ (C # - เพื่อวัตถุประสงค์ตัวอย่าง)

//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];

เสร็จแล้ว


1
ฉันชอบคำตอบแบบง่ายและการอ้างอิงมีดโกนของ Occam มาก แค่ต้องการตรวจสอบอีกครั้งว่าโซลูชันนี้ยังใช้งานได้สำหรับคุณ
Jeff Marino

1
เป็นที่น่าสังเกตว่าหากรีเฟรชหน้าควรเก็บเซสชันไว้วิธีนี้จะไม่ได้ผล แนวทางอื่นที่แนะนำในคำตอบอื่นของการใช้ window.sessionStorage ดูเหมือนจะสมเหตุสมผลสำหรับฉันมากกว่า
rosenfeld

@quijibo ยังคงทำงานได้อย่างสมบูรณ์ในแอปพลิเคชันของฉันใช่ สำหรับการรีเฟรชหน้าเว็บอาจเป็นจริงสำหรับบางเบราว์เซอร์การใช้ window.sessionStorage อาจแก้ปัญหาได้ แต่ยังไม่ได้ลอง
Mike A.

3
ฟังก์ชัน "se_appframe ()" คืออะไร?
AndreMiranda

se_appframeคืออะไร?
Kiquenet

2

คุณสามารถใช้การเขียนลิงก์ใหม่เพื่อต่อท้ายตัวระบุที่ไม่ซ้ำกันกับ URL ทั้งหมดของคุณเมื่อเริ่มต้นที่หน้าเดียว (เช่น index.html / jsp / อะไรก็ตาม) เบราว์เซอร์จะใช้คุกกี้เดียวกันสำหรับทุกแท็บของคุณดังนั้นทุกสิ่งที่คุณใส่ไว้ในคุกกี้จะไม่ซ้ำกัน


2
ฉันคิดว่าการเขียนลิงก์ใหม่เพื่อเข้ารหัสเซสชันเป็นเรื่องที่น่าเบื่อและเกิดข้อผิดพลาดได้ง่าย ฉันมีแอปพลิเคชันขนาดใหญ่พร้อมลิงก์จำนวนมากฉันต้องการโซลูชันที่โปร่งใสหรือใช้งานง่าย
Oriol Terradas

2

ฉันคิดว่าสิ่งที่คุณอาจต้องการคือการรักษาสถานะการนำทางในแท็บต่างๆไม่ใช่การสร้างเซสชันเดียวต่อแท็บ นี่คือสิ่งที่เฟรมเวิร์ก Seam ประสบความสำเร็จด้วยขอบเขต / บริบทการสนทนา การใช้งานของพวกเขาขึ้นอยู่กับข้อเท็จจริงที่ว่า ID การสนทนาถูกเผยแพร่ไปพร้อมกับแต่ละคำขอและสร้างแนวคิดของการสนทนาทางฝั่งเซิร์ฟเวอร์ซึ่งเป็นสิ่งที่อยู่ระหว่างเซสชันและคำขอ ช่วยให้สามารถควบคุมโฟลว์การนำทางและการจัดการสถานะ

แม้ว่าจะมุ่งเป้าไปที่ JSF เป็นหลัก แต่ลองดูและตรวจสอบว่านั่นคือสิ่งที่คุณสามารถนำแนวคิดบางอย่างได้จาก: http://docs.jboss.org/seam/latest/reference/en-US/html_single/#d0e3620


2

ในจาวาสคริปต์ฉันจะระบุหน้าต่างเบราว์เซอร์หนึ่งโดยไม่ซ้ำกันจากหน้าต่างอื่นซึ่งอยู่ภายใต้เซสชันที่ใช้การปรุงอาหารเดียวกัน

ใช้ window.name เป็นหลัก หากไม่ได้ตั้งค่าให้ตั้งค่าเป็นค่าเฉพาะและใช้งาน ซึ่งจะแตกต่างกันไปตามแท็บต่างๆที่อยู่ในเซสชันเดียวกัน


1

อีกวิธีหนึ่งที่ใช้ได้ผลคือการสร้างรหัสหน้าต่างเฉพาะและเก็บค่านี้พร้อมกับรหัสเซสชันในตารางฐานข้อมูล รหัสหน้าต่างที่ฉันมักใช้คือจำนวนเต็ม (ตอนนี้) ค่านี้ถูกสร้างขึ้นเมื่อเปิดหน้าต่างและกำหนดให้กับหน้าต่างเดิมใหม่หากหน้าต่างถูกรีเฟรชโหลดซ้ำหรือส่งไปยังตัวมันเอง ค่าหน้าต่าง (อินพุต) จะถูกบันทึกไว้ในตารางภายในเครื่องโดยใช้ลิงก์ เมื่อต้องการค่าจะได้รับจากตารางฐานข้อมูลตามลิงค์ id หน้าต่าง / รหัสเซสชัน แม้ว่าวิธีการนี้จะต้องใช้ฐานข้อมูลในเครื่อง การใช้ตารางฐานข้อมูลเป็นเรื่องง่ายสำหรับฉัน แต่ฉันไม่เห็นเหตุผลว่าทำไมอาร์เรย์ภายในเครื่องจึงใช้งานไม่ได้เช่นกัน


1

ฉันได้พัฒนาวิธีแก้ปัญหานี้เมื่อเร็ว ๆ นี้โดยใช้คุกกี้ นี่คือลิงค์ไปยังโซลูชันของฉัน ฉันได้รวมโค้ดตัวอย่างของโซลูชันโดยใช้ ASP.NET คุณควรจะสามารถปรับใช้กับ JSP หรือ Servelets ได้หากต้องการ

https://sites.google.com/site/sarittechworld/track-client-windows



1

หมายเหตุ: การแก้ปัญหาที่นี่ต้องทำในขั้นตอนการออกแบบแอปพลิเคชัน มันจะยากที่จะสร้างสิ่งนี้ในภายหลัง

ใช้ข้อมูลที่ซ่อนอยู่จะผ่านรอบตัวระบุเซสชั่น

เพื่อให้ทำงานได้แต่ละหน้าต้องมีแบบฟอร์ม:

<form method="post" action="/handler">

  <input type="hidden" name="sessionId" value="123456890123456890ABCDEF01" />
  <input type="hidden" name="action" value="" />

</form>

ทุกการกระทำที่อยู่เคียงข้างคุณรวมถึงการนำทางโพสต์แบบฟอร์มกลับ (ตั้งค่าactionตามความเหมาะสม) สำหรับคำขอ"ไม่ปลอดภัย"คุณสามารถใส่พารามิเตอร์อื่นเช่นมีค่า JSON ของข้อมูลที่จะส่ง:

<input type="hidden" name="action" value="completeCheckout" />
<input type="hidden" name="data" value='{ "cardNumber" : "4111111111111111", ... ' />

เนื่องจากไม่มีคุกกี้แต่ละแท็บจึงเป็นอิสระและจะไม่มีความรู้เกี่ยวกับเซสชันอื่น ๆ ในเบราว์เซอร์เดียวกัน

ข้อดีมากมายโดยเฉพาะในเรื่องความปลอดภัย:

  • ไม่ต้องพึ่งพา JavaScript หรือ HTML5
  • โดยเนื้อแท้ป้องกันCSRF
  • ไม่มีความเชื่อมั่นเกี่ยวกับคุกกี้เพื่อป้องกันพุดเดิ้ล
  • ไม่เสี่ยงต่อการตรึงเซสชั่น
  • สามารถป้องกันการใช้ปุ่มย้อนกลับซึ่งเป็นที่พึงปรารถนาเมื่อคุณต้องการให้ผู้ใช้ทำตามเส้นทางที่กำหนดผ่านไซต์ของคุณ (ซึ่งหมายถึงข้อบกพร่องทางตรรกะที่บางครั้งอาจถูกโจมตีจากคำขอที่ไม่ได้รับคำสั่งสามารถป้องกันได้)

ข้อเสียบางประการ:

  • อาจต้องการฟังก์ชันปุ่มย้อนกลับ
  • ไม่ค่อยได้ผลกับการแคชเนื่องจากทุกการกระทำเป็น POST

ข้อมูลเพิ่มเติมที่นี่


1

ฉันแก้ไขด้วยวิธีต่อไปนี้:

  • ฉันได้กำหนดชื่อให้กับหน้าต่างชื่อนี้เหมือนกับทรัพยากรการเชื่อมต่อ
  • บวก 1 เพื่อกำจัดที่เก็บไว้ในคุกกี้เพื่อแนบการเชื่อมต่อ
  • ฉันได้สร้างฟังก์ชันเพื่อจับการตอบสนอง xmloutput ทั้งหมดและกำหนด sid และ rid ให้กับคุกกี้ในรูปแบบ json ฉันทำสิ่งนี้สำหรับแต่ละ window.name

ที่นี่รหัส:

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);
    }

ฉันหวังว่าจะช่วยคุณ


0

ฉันอ่านโพสต์นี้เพราะฉันคิดว่าฉันอยากจะทำสิ่งเดียวกัน ฉันมีสถานการณ์คล้ายกันสำหรับแอปพลิเคชันที่ฉันกำลังทำงานอยู่ และจริงๆแล้วมันเป็นเรื่องของการทดสอบมากกว่าการใช้งานจริง

หลังจากอ่านคำตอบเหล่านี้โดยเฉพาะคำตอบที่ Michael Borgwardt มอบให้ฉันตระหนักถึงขั้นตอนการทำงานที่ต้องมีอยู่:

  1. หากผู้ใช้ไปที่หน้าจอเข้าสู่ระบบให้ตรวจสอบเซสชันที่มีอยู่ หากมีอยู่ให้ข้ามหน้าจอการเข้าสู่ระบบและส่งไปที่หน้าจอต้อนรับ
  2. หากผู้ใช้ (ในกรณีของฉัน) ไปที่หน้าจอการลงทะเบียนให้ตรวจสอบเซสชันที่มีอยู่ หากมีอยู่ให้แจ้งให้ผู้ใช้ทราบว่าคุณกำลังจะออกจากเซสชันนั้น หากพวกเขาเห็นด้วยให้ออกจากระบบและเริ่มการลงทะเบียน

วิธีนี้จะแก้ปัญหาผู้ใช้เห็นข้อมูล "ผู้ใช้รายอื่น" ในเซสชันของตน พวกเขาไม่เห็นข้อมูล "ผู้ใช้รายอื่น" ในเซสชันของพวกเขาจริงๆพวกเขาเห็นข้อมูลจากเซสชันเดียวที่เปิดอยู่ เห็นได้ชัดว่านี่เป็นสาเหตุของข้อมูลที่น่าสนใจเนื่องจากการดำเนินการบางอย่างเขียนทับข้อมูลเซสชันบางส่วนไม่ใช่ข้อมูลอื่น ๆ ดังนั้นคุณจึงมีการรวมกันของข้อมูลในเซสชันเดียวนั้น

ตอนนี้เพื่อแก้ไขปัญหาการทดสอบ แนวทางเดียวที่เป็นไปได้คือการใช้ประโยชน์จากPreprocessor Directivesเพื่อพิจารณาว่าควรใช้เซสชันที่ไม่ใช้คุกกี้หรือไม่ ดูจากการสร้างในการกำหนดค่าเฉพาะสำหรับสภาพแวดล้อมเฉพาะฉันสามารถตั้งสมมติฐานบางอย่างเกี่ยวกับสภาพแวดล้อมและสิ่งที่ใช้สำหรับ สิ่งนี้จะช่วยให้ฉันมีผู้ใช้สองคนเข้าสู่ระบบในเวลาเดียวกันในทางเทคนิคและผู้ทดสอบสามารถทดสอบหลายสถานการณ์จากเซสชันเบราว์เซอร์เดียวกันโดยไม่ต้องออกจากระบบเซสชันเซิร์ฟเวอร์ใด ๆ

อย่างไรก็ตามแนวทางนี้มีข้อควรระวังบางประการ อย่างน้อยที่สุดก็คือความจริงที่ว่าสิ่งที่ผู้ทดสอบกำลังทดสอบไม่ใช่สิ่งที่กำลังจะดำเนินการในการผลิต

ดังนั้นฉันคิดว่าฉันต้องบอกว่านี่เป็นความคิดที่ไม่ดีในที่สุด


0

การจัดเก็บ timeStamp ใน window.sessionStorage หากยังไม่ได้ตั้งค่า ค่านี้จะให้ค่าที่ไม่ซ้ำกันสำหรับแต่ละแท็บ (แม้ว่า URL จะเหมือนกันก็ตาม)

http://www.javascriptkit.com/javatutors/domstorage.shtml

https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage

หวังว่านี่จะช่วยได้


1
นี่อาจจะใช้ได้ แต่ในทางทฤษฎีไม่ปลอดภัย ระบบปฏิบัติการบางระบบ (เช่น Windows) มีรายละเอียดการประทับเวลาที่หยาบมากซึ่งหมายความว่าคุณอาจค้นหาการประทับเวลาหลายครั้งและได้รับค่าเดิมกลับมา นอกจากนี้หากคุณเปิดเบราว์เซอร์อีกครั้งหลังจากเกิดข้อขัดข้องและเปิดแท็บทั้งหมดขึ้นมาใหม่ในครั้งเดียวพวกเขาอาจได้รับการประทับเวลาเดียวกัน
Gili

0
How to differ sessions in browser-tabs?

วิธีที่ตรงไปตรงมาที่สุดในการใช้งานเซสชันต่างๆในแท็บเบราว์เซอร์คือการไม่อนุญาตให้โดเมนของคุณตั้งค่าคุกกี้ ด้วยวิธีนี้คุณสามารถมีเซสชันแยกจากแท็บต่างๆ สมมติว่าคุณไม่อนุญาตคุกกี้จากโดเมนนี้: www.xyz.com คุณเปิดแท็บ 1 เข้าสู่ระบบและเริ่มการเรียกดู จากนั้นคุณเปิดแท็บ 2 และคุณสามารถเข้าสู่ระบบในฐานะผู้ใช้คนเดียวกันหรือผู้อื่น ไม่ว่าจะด้วยวิธีใดคุณจะมีเซสชันแยกจากแท็บ 1 และอื่น ๆ

แต่แน่นอนว่าเป็นไปได้เมื่อคุณมีอำนาจควบคุมฝั่งไคลเอ็นต์ มิฉะนั้นควรใช้วิธีแก้ปัญหาที่กำหนดโดยคนที่นี่


0

คุณจะต้องทำ

1- เก็บคุกกี้สำหรับรายการบัญชี

2- เก็บคุกกี้ที่เป็นทางเลือกสำหรับค่าเริ่มต้น

3- จัดเก็บสำหรับแต่ละบัญชีด้วยดัชนีเช่น acc1, acc2

4- ใส่ url บางอย่างแทนดัชนีของบัญชีและถ้าไม่ใช่คุณจะเลือกค่าเริ่มต้นเช่น google mail domain.com/0/some-url >> 0 ที่นี่แสดงถึงดัชนีของบัญชีคุณอาจต้องรู้วิธีการ ใช้ urlwrite

5- เมื่อเลือกคุกกี้ให้เลือกตาม urlpath ของคุณแสดงดัชนีบัญชี

ความนับถือ


0

ฉันเห็นการใช้งานจำนวนมากที่มีการเปลี่ยนแปลงฝั่งไคลเอ็นต์เพื่อจัดการคุกกี้รหัสเซสชัน แต่โดยทั่วไปคุกกี้รหัสเซสชันควรเป็น HttpOnly ดังนั้น java-script จึงไม่สามารถเข้าถึงได้มิฉะนั้นอาจนำไปสู่ ​​Session Hijack ผ่าน XSS


0

หากเป็นเพราะแต่ละแท็บจะเรียกใช้โฟลว์ที่แตกต่างกันในแอปพลิเคชันของคุณและการผสมโฟลว์ทั้งสองทำให้เกิดปัญหาควร "กำหนดภูมิภาค" วัตถุเซสชันของคุณจะดีกว่าเพื่อให้แต่ละโฟลว์ใช้พื้นที่ที่แตกต่างกันของเซสชัน

ภูมิภาคนี้สามารถใช้งานได้เพียงแค่มีคำนำหน้าที่แตกต่างกันสำหรับแต่ละโฟลว์หรือวัตถุเซสชันจะมีหลายแผนที่ (หนึ่งรายการสำหรับแต่ละโฟลว์) และคุณใช้แผนที่เหล่านั้นแทนแอตทริบิวต์เซสชัน แต่วิธีที่ดีที่สุดคือการขยายคลาสเซสชันของคุณและ ใช้แทน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.