2016-10-17 4 views
1

Ich habe eine einfache Backbone.js App, die json-server als Backend verwendet. Ich habe eine Funktion, um mich anzumelden, die einen Benutzer aus der Sammlung findet, aber ich bekomme nicht, wie ich meine Sitzung speichern werde. Ich habe darüber nachgedacht, einen Parameter in Cookies zu speichern, der später bei jeder Weiterleitung überprüft wird. Hier ist mein Modell:Session-Parameter in Cookies speichern

var User = Backbone.Model.extend({ 
    defaults: { 
     login: '', 
     password: '', 
     authToken: '' 
    } 
}); 

Und hier ist meine Sammlung:

var UserCollection = Backbone.Collection.extend({ 
    url: 'http://localhost:3000/users', 

    // creates a random token 
    setToken: function() { 
     var rand = function() { 
      return Math.random().toString(36).substr(2) 
     } 

     var token = rand() + rand(); 
     this.set({authToken: token}); 
    } 
}); 

Und das ist die Ansicht mit Login-Funktion

var LoginView = Backbone.View.extend({ 
    initialize: function() { 
     this.collection = new UserCollection(); 
     // template 
    } 
    // render function omitted 

    signIn: function() { 
     var login = $('#login').val(); 
     var password = $('#password').val(); 

     /** 
      finds a user within with the values from input fields 
      inside the collection 
     */ 
     if (login && password) { 
      this.collection.fetch({ 
       data: { 
        login: login, 
        password: password 
       } 
      }); 
     } 
    } 
}); 

Diese Funktion gibt mir ein Array mit einem Objekt, das ist mein Wunschmodell. Alles, was ich brauche, ist meine setToken Methode zu verwenden und dieses Modell authToken in Cookie zu speichern, damit ich es an anderer Stelle in der App verwenden konnte, aber ich bekomme eigentlich nicht, wie man das macht.

Antwort

1

Die Verwendung eines Modells zur Authentifizierung wäre sinnvoller als eine Sammlung. Halte die Verantwortung des Modells einfach und beschränke dich auf eine Sache. Ein Modell zur Handhabung der Authentifizierung, dann ein Modell zur Verarbeitung von Aufrufen an andere Objekte, die authentifiziert werden müssen, und nicht gleichzeitig.

Ich persönlich basierte Authentifizierung auf Backbone-session Modell.

// Using CommonJS 
var Session = require('backbone-session'); 

// Extend from Session to implement your API's behaviour 
var Account = Session.extend({ 
    urlRoot: 'http://localhost:3000/users', 
    signIn: function(opt) { 
     opt = opt || {}; 
     opt.data = _.extend({}, { 
      login: opt.login, 
      password: opt.password 
     }, opt.data); 
     return this.fetch(opt); 
    }, 
    signOut: function(opt) { /** handle logout */ }, 
    getAuthStatus: function() { /** handle refetching if needed */ } 
}); 

Welche ich als Service für meine Anwendung aussetzen. In diesem session-Modul überschreibe ich Backbone.Sync, um die Authentifizierung für alle folgenden Aufrufe der API für alle Modelle oder Auflistungen sicherzustellen.

var mySession = new Account(); 


Backbone.sync = (function(syncFn) { 
    return function(method, model, options) { 
     options = options || {}; 

     var beforeSend = options.beforeSend, 
      error = options.error; 

     // Add auth headers 
     options.beforeSend = function(xhr) { 
      xhr.setRequestHeader('Authorization', "Bearer " + mySession.get('authToken')); 
      if (beforeSend) return beforeSend.apply(this, arguments); 
     }; 

     // handle unauthorized error (401) 
     options.error = function(xhr, textStatus, errorThrown) { 
      if (error) error.call(options.context, xhr, textStatus, errorThrown); 
      if (xhr.status === 401) { 
       mySession.signOut(); 
      } 
     }; 

     return syncFn.apply(this, arguments); 
    }; 
})(Backbone.sync); 

Das Modell der Backbone-Sitzung verwendet den lokalen Speicher als Back-End. Eigene sync method is overriden, um den lokalen Speicher anstelle des Standardverhaltens sync zu verwenden.

sync: function(method, model, options) { 
    options = options || {}; 
    var url = model.options.url || model.url; 
    var key = _.isFunction(url) ? url() : '' + url; 
    var response; 
    switch (method) { 
    case 'create': 
    case 'update': 
     var data = model.toJSON(); 
     var text = JSON.stringify(data); 
     response = localStorage.setItem(key, text); 
     break; 
    case 'delete': 
     response = localStorage.removeItem(key); 
     break; 
    case 'read': 
     response = JSON.parse(localStorage.getItem(key)); 
     break; 
    } 
    if (_.isFunction(options.success)) { 
    options.success(response); 
    } 
    return Backbone.$.Deferred() 
    .resolve(response) 
    .promise(); 
}, 

Warum der lokale Speicher?

Sie können diese Implementierung verwenden und sie minimal ändern, um stattdessen Cookies zu verwenden.

Der lokale Speicher war eine bessere Option für mich, da meine API in einer anderen Domäne ist und CORS verwendet, um den öffentlichen Zugriff zu ermöglichen. Safari has limitation on cookies.

Safari blockiert auch Cookies von Websites, die besucht wurden nicht direkt. Sie können in den Sicherheitseinstellungen sehen. Es ist die Standardeinstellung ist Cookies akzeptieren: "Nur von Websites, die ich besuche".

Verwandte Themen