2010-03-25 12 views
15

Ho un'applicazione ASP.net che è fondamentalmente una schermata di immissione dei dati per un processo di ispezione fisica. Gli utenti vogliono essere in grado di avere più finestre del browser aperte e immettere dati da più ispezioni contemporaneamente. All'inizio usavo sessioni basate sui cookie, e ovviamente questo esplose.Come impedire a più finestre del browser di condividere la stessa sessione in asp.net

Sono passato a utilizzare sessioni senza cookie, che memorizza la sessione nell'URL e in fase di test sembrava risolvere il problema. Ciascuna finestra/scheda del browser aveva un ID di sessione diverso e i dati inseriti in uno non contenevano dati inseriti nell'altro.

Tuttavia i miei utenti sono più efficienti nel rompere le cose di quanto mi aspettassi e sembra che stiano ancora riuscendo a ottenere la stessa sessione tra i browser a volte. Penso che stiano copiando/incollando l'indirizzo da una scheda all'altra per poter aprire l'applicazione, ma non sono ancora riuscito a verificarlo (sono in un'altra posizione quindi non posso chiedere loro facilmente).

Oltre a dire loro di non copiare e incollare o convincerli a inserire solo uno alla volta, come posso evitare che si verifichi questa situazione?

+1

Potrei sbagliarmi (quindi non inserire questo come risposta), ma credo che questa sia una limitazione del browser. A parte il metodo cookieless che hai provato, non credo che sarà molto facile per i browser utilizzare sessioni indipendenti tra tutte le schede. Peggio ancora, anche se gestisci un browser per farlo, ci sono ancora gli altri da "riparare". – keyboardP

risposta

4

Pensare di utilizzare ViewState anziché Session, poiché ViewState restituisce informazioni sullo stato al client (pagina HTML). Non sono sicuro che sarai mai in grado di ottenere un controllo dettagliato sul comportamento della sessione del browser, poiché l'ID della sessione viene gestito dal browser nel modo in cui lo ha fatto il produttore. Quindi ViewState è più predicibile, non solo, ma anche per versioni future del browser.

+1

Giusto per chiarire, con 'sicuro', suppongo che tu non intenda dal punto di vista di un attacco di hacker. – keyboardP

+0

No, no, hai ragione. Ho modificato il post. –

2

Gli utenti devono accedere con account diversi per accedere a ispezioni fisiche diverse? Mi sembra che fino a quando lo PhysicalInspectionID fa parte dell'URL, quindi non ci dovrebbero essere problemi nella modifica di più ispezioni fisiche allo stesso tempo.

esempio

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

Naturalmente, se si copia l'URL, che riceveranno un duplicato della altra finestra, ma questo insegnerà loro di non farlo. Invece, aprono un'altra finestra e passano all'ispezione corretta (o ne aggiungono una nuova) tramite l'interfaccia utente.

0

Creare un nuovo ID di sessione quando la richiesta non ha alcun riferimento. Questo risolve il problema dell'URL di copia-incolla. Memorizza il sessionId nella url come hai fatto tu.

3

questa è una domanda molto buona che ho anche pensato a lungo e duramente.

Memorizza la tua pagina Web principale in un iframe. Avere javascript per controllare se la tua pagina web è ancora nell'iframe genitore. In caso contrario, hanno aperto più finestre del browser.

È necessario assicurarsi che l'intera app sia iframe friendly.

+3

lo hai effettivamente detto. All'inizio ho pensato che stavi scherzando, ma non penso che lo sei. IFRAME? – jDeveloper

3

Non sono sicuro del motivo per cui si desidera limitare una sessione per gestire un solo processo di ispezione e quindi forzare più sessioni affinché gli utenti possano lavorare contemporaneamente su più ispezioni. Mi sembra uno stile di isolamento piuttosto imbarazzante.

L'applicazione Web (e le pagine) devono essere in grado di gestire più processi di ispezione all'interno di una singola sessione utente.

Qualsiasi dato contenuto nelle variabili di sessione non deve essere chiaramente esposto per la gestione singolare.Dovrebbero essere memorizzati nelle collezioni che identificano facilmente quale gruppo di dati appartiene a quale processo di ispezione. Ogni invio di pagina al server Web deve contenere un identificatore a cui si riferisce il processo di ispezione, in modo che il set di sessione corretto possa essere abbinato e tirato per l'uso.

concetto pseudo codice

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

Questo è quello che uso in ASP.NET MVC proibire utenti autenticati di aprire più schede:

<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> 

Fondamentalmente, questo imposta il nome della finestra prima volta quando l'utente visita la pagina di accesso. Dopo l'accesso, per ogni caricamento successivo della pagina viene verificato il nome della finestra.

due problemi:

  • non fa wok se JavaScript disabilitato
  • se per errore l'utente chiude la scheda originale e poi incolla qualche altro link al mio sito web nella barra degli indirizzi, l'utente riceverà sempre la pagina di errore. Per dare all'utente la possibilità di recuperare, ho incluso il link "Esci" nella pagina SingleTab.htm, in modo che l'utente possa distruggere il suo cookie di sessione e avviare una nuova sessione.
2

Una soluzione a questo problema può essere implementato dal seguente:

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

Aggiungere un servizio ASMX web (o qualsiasi altro tipo di servizi che si pensa è adatto) al progetto principale e aggiungere il seguente metodo ad esso:

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

Nella pagina master, o in ogni pagina aggiungere il seguente javascript:

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

Nota che il tempo di risposta del tuo sito è influenzato dalla velocità del servizio web.

+0

Cosa succederà se l'utente gira di JavaScript? – kat1330

+0

È possibile rilevarlo e impedire all'utente di eseguire operazioni fin dal primo avvio. Promettilo per abilitare JavaScript. – yazanpro

+0

È possibile sostituire la chiamata del servizio Web con una chiamata Ajax a una pagina all'interno dell'applicazione Web. – ZooZ

Problemi correlati