Συνεδρίες & Ασφάλεια

Συνεδρίες εγγράφων και έλεγχος πρόσβασης

Ένα Doconut token αναγνωρίζει ένα ανοιχτό έγγραφο. Εάν εξυπηρετηθεί οποιοδήποτε αίτημα που το μεταφέρει, όποιος το απέκτησε θα μπορούσε να διαβάσει κάθε σελίδα. Αυτή η σελίδα εξηγεί τι περιέχει μια συνεδρία εγγράφου, πόσο διαρκεί και πώς DocImage.axd αποφασίζει ποιος μπορεί να δει τις σελίδες του — σε έναν διακομιστή και σε μια φάρμα web.

Τι περιέχει μια συνεδρία εγγράφου

Κάθε επιτυχής OpenDocumentAsync δημιουργεί μια συνεδρία, που διατηρείται στη μνήμη:

  • το loaded format viewer — η παρουσία της μηχανής που κρατά το αναλυμένο έγγραφο,
  • per-page state — περιστροφή, αναστροφές και τα δεδομένα σχολιασμού που ο χρήστης εφαρμόζει στο widget,
  • το προαιρετικό search index, δημιουργείται στην πρώτη αναζήτηση (ή φορτώνεται από ένα προ-κατασκευασμένο αρχείο .srh),
  • το watermark της συνεδρίας από DocOptions.Watermark.

Διάρκεια ζωής

Οι συνεδρίες λήγουν σε ένα sliding window: DocOptions.TimeOut λεπτά (προεπιλογή 60), επαναφέρονται από κάθε αίτημα που παρουσιάζει το token. Όταν μια συνεδρία τελειώνει — λόγω λήξης ή λόγω CloseDocument(token) — η μηχανή του εγγράφου απελευθερώνεται και η μνήμη του ελευθερώνεται αμέσως.

csharp
// Μια βραχύβια συνεδρία για μια εφάπαξ προεπισκόπηση
var token = await viewer.OpenDocumentAsync(path, new DocOptions { TimeOut = 10 });

Ένα αίτημα με ληγμένο token λαμβάνει μια εικόνα σφάλματος που διαβάζει Document session not found. Please re-open document.. Η σελίδα πρέπει να ανοίξει ξανά το έγγραφο για να πάρει νέο token. Σε έναν μοναδικό διακομιστή, η ανακύκλωση της ομάδας εφαρμογών τερματίζει επίσης κάθε συνεδρία.

Οι σελίδες εξυπηρετούνται μόνο στη συνεδρία που τις άνοιξε

Με UnsafeMode = false — η προεπιλογή — το άνοιγμα ενός εγγράφου χορηγεί πρόσβαση στην συνεδρία ASP.NET του αιτήματος που το άνοιξε, γράφοντας μια καταχώρηση secure-{token} σε αυτή τη συνεδρία. DocImage.axd απαιτεί την ίδια την κατάσταση συνεδρίας, και εξυπηρετεί μια σελίδα μόνο όταν η συνεδρία του αιτούντος περιέχει αυτήν την καταχώρηση. Οποιοσδήποτε άλλος περιηγητής που παρουσιάζει το ίδιο token λαμβάνει μια εικόνα σφάλματος που διαβάζει You Are Not Authorized To View This Page..

csharp
Doconut.DoconutHost.Initialize(options =>
{
    // false (η προεπιλογή): το DocImage.axd εξυπηρετεί μια σελίδα μόνο στη συνεδρία ASP.NET που την άνοιξε
    // το έγγραφο. Ο διαχειριστής ζητά την κατάσταση της συνεδρίας μόνο του· χρειάζεται μόνο το site να μην
    // απενεργοποιήσει την κατάσταση της συνεδρίας στο Web.config.
    options.UnsafeMode = false;
});
  • Το άνοιγμα του endpoint απαιτεί κατάσταση συνεδρίας. Οι ελεγκτές MVC και οι σελίδες Web Forms τη διαθέτουν από προεπιλογή. Ένα προσαρμοσμένο IHttpHandler δεν τη διαθέτει εκτός αν υλοποιεί System.Web.SessionState.IRequiresSessionState. Ένα άνοιγμα που εκτελείται χωρίς συνεδρία δεν έχει τίποτα να χορηγήσει, έτσι ο προβολέας εμφανίζει «Δεν Είστε Εξουσιοδοτημένος Να Δείτε Αυτή Τη Σελίδα.» σε κάθε σελίδα.
  • Η κατάσταση συνεδρίας πρέπει να παραμένει ενεργή. <sessionState mode="Off" /> στο Web.config απενεργοποιεί τόσο την χορήγηση όσο και τον έλεγχο, και κάθε σελίδα απορρίπτεται.
  • Ο περιηγητής πρέπει να στέλνει το cookie της συνεδρίας. Τα αιτήματα του widget είναι same-origin, έτσι μεταφέρουν αυτόματα το ASP.NET_SessionId. Ένας πελάτης χωρίς δοχείο cookie — ένα script, μια κλήση server-to-server, μια ρύθμιση cross-origin που αφαιρεί τα cookies — απορρίπτεται. Αυτό είναι το χαρακτηριστικό που λειτουργεί.

UnsafeMode = true απενεργοποιεί τον έλεγχο: οποιοδήποτε αίτημα που μεταφέρει το token εξυπηρετείται. Είναι ένας παγκόσμιος διακόπτης για κάθε έγγραφο, χωρίς δυνατότητα παρακάμψης ανά έγγραφο. Αφήστε το false.

Ανάκληση

CloseDocument(token) κάνει περισσότερα από το να ελευθερώσει μνήμη: αφαιρεί την καταχώρηση secure-{token} από τη συνεδρία του τρέχοντος αιτήματος και ανακαλεί το token, έτσι ένα κλειστό token απορρίπτεται αμέσως.

Φάρμες Web: υπογεγραμμένα εισιτήρια

Σε μια φάρμα, το επόμενο αίτημα μπορεί να καταλήξει σε έναν διακομιστή που δεν έχει δει ποτέ το έγγραφο, σε διαφορετική διεργασία worker, με τη δική του συνεδρία ASP.NET. Η χορήγηση της συνεδρίας δεν μπορεί να το ακολουθήσει. Η κατανεμημένη λειτουργία την αντικαθιστά με ένα signed ticket δεσμευμένο στον περιηγητή: κάθε κόμβος μοιράζεται ένα αποθηκευτικό χώρο για συνεδρίες εγγράφων και ένα κλειδί υπογραφής, και DocImage.axd δέχεται ένα αίτημα όταν το εισιτήριό του είναι έγκυρο για το token, τον περιηγητή, και — όταν ο χρήστης είναι συνδεδεμένος — για αυτόν τον χρήστη.

Η ρύθμιση, ταυτόσημη σε κάθε κόμβο:

csharp
// Global.asax.cs - Application_Start
Doconut.DoconutHost.Initialize(
    options => options.UnsafeMode = false,     // ο έλεγχος εισιτηρίου εκτελείται μόνο όταν αυτό είναι false
    services => services.AddDoconutDistributed(d =>
    {
        d.Store             = CloudLocation.FileShare;
        d.FileShareRootPath = @"\\fileserver\doconut-shared";  // ένας φάκελος που μπορεί να προσεγγίσει κάθε κόμβος
        d.SigningKey        = farmKey;                          // τουλάχιστον 32 byte, το ίδιο σε κάθε κόμβο
    }));

Το endpoint ανοίγματος στη συνέχεια δεσμεύει το εισιτήριο στον περιηγητή πριν το άνοιγμα, και επιστρέφει το εισιτήριο μαζί με το token:

  • ορίστε DocOptions.BrowserId = DoconutFarmBinding.EnsureBrowserId(System.Web.HttpContext.Current, securityOptions) — εκδίδει το cookie doconut-client στο οποίο είναι δεσμευμένο το εισιτήριο — και DocOptions.UserId = DoconutFarmBinding.ResolveUserId(System.Web.HttpContext.Current);
  • μετά από OpenDocumentAsync, επιστρέψτε viewer.AccessToken μαζί με το token;
  • στη σελίδα, περάστε και τα δύο στο widget: objViewer.View(token, access).

Doconut.MvcSample.WebFarm στο πακέτο παραδειγμάτων είναι ένας πλήρης, εκτελέσιμος κόμβος φάρμας, και ο οδηγός μετάβασης δίπλα του εξηγεί κάθε βήμα.

Κρατήστε το κλειδί υπογραφής εκτός ελέγχου πηγαίου κώδικα: υπογράφει τα εισιτήρια και κρυπτογραφεί τα έγγραφα στο κοινόχρηστο αποθετήριο. Ένας κόμβος με διαφορετικό κλειδί απορρίπτει κάθε εισιτήριο που έχουν εκδώσει οι άλλοι.

Δοκιμάστε μια φάρμα με πραγματικό περιηγητή, ή με script που διατηρεί cookies. Ένας πελάτης χωρίς το cookie doconut-client δεν λαμβάνει απάντηση με 401: λαμβάνει την εικόνα σφάλματος «δεν εξουσιοδοτημένο» με κατάσταση 200, περίπου 2 KB, ενώ μια πραγματική σελίδα είναι δεκάδες έως εκατοντάδες kilobytes.

Λίστα ελέγχου παραγωγής

  • Διατηρήστε το UnsafeMode = false (η προεπιλογή).
  • Ανοίξτε έγγραφα από αιτήματα που διαθέτουν κατάσταση συνεδρίας, και μην απενεργοποιείτε ποτέ την κατάσταση συνεδρίας.
  • Βεβαιωθείτε ότι το cookie της συνεδρίας φθάνει στο DocImage.axd (ίδιο προέλευση, HTTPS, μια πολιτική SameSite που το επιτρέπει).
  • Σε μια φάρμα, χρησιμοποιήστε κατανεμημένη λειτουργία με ένα κλειδί υπογραφής κοινόχρηστο από κάθε κόμβο.
  • Καλέστε το CloseDocument όταν ο χρήστης αφήνει ένα έγγραφο — ωφελούνται τόσο η μνήμη όσο και η ασφάλεια.
  • Ποτέ μην καταγράφετε ή μοιράζεστε tokens· αντιμετωπίζετε τα ως βραχύβια διαπιστευτήρια.

Ήταν αυτή η σελίδα χρήσιμη;