2013-04-05 15 views
32

Alcune aree della SPA devono essere aperte a tutti gli utenti e alcune aree richiedono l'autenticazione. In queste aree, sono i dati caricati tramite AJAX che voglio proteggere.Token di autenticazione MVC e antifora con modello Durandal SPA

Ho un servizio di autenticazione (vedi sotto), che aggiungo come dipendenza nel mio dur.. Il servizio si chiama:

authentication 

Nei miei main.js io chiamo

authentication.handleUnauthorizedAjaxRequest(function() { 
     app.showMessage('You are not authorized, please login') 
     .then(function() { 
      router.navigateTo('#/user/login'); 
     }); 
    }); 

Si avverte l'utente che non sono autorizzati, e naviga utente ad una vista di login/viewmodel dove possono entrare dettagli e prova ad accedere

Alcune domande che vengono in mente quando si costruisce questa autenticazione ViewModel:.

  • Ci sono ovvi problemi con quello che sto facendo?
  • È così che sono "intenzionato" a fare cose a Durandal?
  • Sto reinventando la ruota? Non potevo vedere nulla di simile in Durandal.

La maggior parte delle persone sembra creare pagine separate cshtml; uno per login (se l'utente non è autenticato), e il solito index.cshtml Ci sono dei buoni motivi per passare a quel metodo?

La mia azione di accesso sul mio 'controller utente' lato server ha l'attributo [ValidateAntiForgeryToken] che devo inviare anche a questo.
Ho anche un servizio di "antiforgery" (vedi sotto) che aggiungo anche come dipendenza nel mio main.js viewModel file quindi (anche nel mio main.js).

antiforgery.addAntiForgeryTokenToAjaxRequests(); 

Questo intercetta tutte le richieste Ajax (insieme con il contenuto), e aggiunge il valore di MVC AntiForgeryToken ai dati. Sembra funzionare esattamente come voglio. Per favore fatemi sapere se ci sono errori/errori.

Completo servizio di autenticazione di seguito.

// services/authentication.js 
define(function (require) { 
    var system = require('durandal/system'), 
    app = require('durandal/app'), 
    router = require('durandal/plugins/router'); 

    return { 
     handleUnauthorizedAjaxRequests: function (callback) { 
      if (!callback) { 
       return; 
      } 
      $(document).ajaxError(function (event, request, options) { 
       if (request.status === 401) { 
        callback(); 
       } 
      }); 
     }, 

     canLogin: function() {   
      return true; 
     }, 
     login: function (userInfo, navigateToUrl) { 
      if (!this.canLogin()) { 
       return system.defer(function (dfd) { 
        dfd.reject(); 
       }).promise(); 
      } 
      var jqxhr = $.post("/user/login", userInfo) 
       .done(function (data) { 
        if (data.success == true) { 
         if (!!navigateToUrl) { 
          router.navigateTo(navigateToUrl); 
         } else { 
          return true; 
         } 
        } else { 
         return data; 
        } 
       }) 
       .fail(function (data) { 
        return data; 
       }); 

      return jqxhr; 
     } 
    }; 
}); 

// services/antiforgery.js 
define(function (require) { 
    var app = require('durandal/app'); 

    return { 
     /* this intercepts all ajax requests (with content) 
      and adds the MVC AntiForgeryToken value to the data 
      so that your controller actions with the [ValidateAntiForgeryToken] attribute won't fail 

      original idea came from http://stackoverflow.com/questions/4074199/jquery-ajax-calls-and-the-html-antiforgerytoken 

      to use this 

      1) ensure that the following is added to your Durandal Index.cshml 
      <form id="__AjaxAntiForgeryForm" action="#" method="post"> 
       @Html.AntiForgeryToken() 
      </form> 

      2) in main.js ensure that this module is added as a dependency 

      3) in main.js add the following line 
      antiforgery.addAntiForgeryTokenToAjaxRequests(); 

     */ 
     addAntiForgeryTokenToAjaxRequests: function() { 
      var token = $('#__AjaxAntiForgeryForm  input[name=__RequestVerificationToken]').val(); 
      if (!token) { 
       app.showMessage('ERROR: Authentication Service could not find  __RequestVerificationToken'); 
      } 
      var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(token); 

      $(document).ajaxSend(function (event, request, options) { 
       if (options.hasContent) { 
        options.data = options.data ? [options.data, tokenParam].join("&") :  tokenParam; 
       } 
      }); 
     } 

    }; 
}); 
+0

Hi Stuart, La tua idea è ottima e sto cercando di applicarla nel mio progetto Hot Towel/Durandal. Ho ottenuto i servizi auth e antiforgery, ma non sto ottenendo il servizio auth per intercettare utenti non autorizzati e reindirizzarli alla pagina di accesso. Come lo faccio? devo aggiungere qualcosa a Index.cshtml? Grazie –

+0

Questo è anche sul gruppo Google di DurandalJs - ci sono stati aggiornamenti da altre persone e ho anche aggiunto alcuni esempi di codice - non saranno davvero adatti a un commento qui ... quindi ;-) .. ecco il link https://groups.google.com/forum/?hl=it&fromgroups=#!topic/durandaljs/iq9OPprfob0 – stooboo

risposta

14

Preferisco passare il token antiforgery nell'intestazione. In questo modo è facile analizzare la richiesta sul server perché non è mescolata con i dati del modulo.

Ho quindi creato un filtro azioni personalizzato per verificare il token antifora.

I created a post già su come fare questo.

+0

+1 Buona idea, sembra un posto valido per questo! – mikekidder

+0

Evviva Evan, non avevo pensato di inserire le intestazioni (non ho visto il tuo post così grazie per il collegamento) – stooboo

Problemi correlati