2013-04-05 4 views
32

Некоторые области моего SPA должны быть открыты для всех пользователей, а некоторые области требуют аутентификации. В этих областях это данные, загруженные через AJAX, которые я хочу защитить.Знак аутентификации и антикоррозионной аутентификации MVC с шаблоном SPA Durandal

У меня есть служба аутентификации (см. Ниже), которую я добавляю в качестве зависимости в моем durandal main.js. Услуга называется:

authentication 

В моих main.js я называю

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

предупреждает пользователя, что не разрешено, и переходит пользователя на вид Войти/ViewModel, где они могут войти подробности и попробуйте войти в

Некоторые вопросы, которые приходят на ум при создании этой аутентификации ViewModel:.

  • Есть ли очевидные проблемы с тем, что я делаю?
  • Является ли это «подразумеваемым», чтобы делать вещи в Дюрандале?
  • Я заново изобретаю колесо? Я не мог видеть ничего подобного в Дюрандале.

Большинство людей создается впечатление, что создается отдельно cshtml pages; один для входа в систему (если пользователь не аутентифицирован) и обычный index.cshtml Есть ли веские причины для переключения на этот метод?

Мое действие для входа на мой пользовательский контроллер на стороне сервера имеет атрибут [ValidateAntiForgeryToken], который мне также нужно отправить.
У меня также есть услуга «antiforgery» (см. Ниже), которую я также добавляю в качестве зависимости в моем main.js viewModel file then (также в моем main.js).

antiforgery.addAntiForgeryTokenToAjaxRequests(); 

Это перехватывает все запросы AJAX (наряду с содержанием), и добавляет значение MVC AntiForgeryToken к данным. Кажется, работает так, как я хочу. Пожалуйста, дайте мне знать, есть ли ошибки или ошибки.

Полный сервис аутентификации ниже.

// 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, Ваша идея замечательная, и я пытаюсь применить ее в своем проекте Hot Towel/Durandal. Я получил услуги auth и antiforgery, но я не получаю auth-сервис, чтобы перехватить неавторизованных пользователей и перенаправить их на страницу входа. Как мне это сделать? мне нужно добавить что-то в Index.cshtml? Спасибо –

+0

Это также на DurandalJs Google Group - там были обновления от других людей, и я также добавил некоторые примеры кода - они не будут вписываться в комментарий здесь ... так ;-) .. вот ссылка https://groups.google.com/forum/?hl=ru&fromgroups=#!topic/durandaljs/iq9OPprfob0 – stooboo

ответ

14

Я предпочитаю пропускать токен antiforgery в заголовке. Таким образом, его легко разобрать из запроса на сервере, потому что он не смешивается с данными вашей формы.

Затем я создал настраиваемый фильтр действий, чтобы проверить токен antiforgery.

I created a post уже о том, как это сделать.

+0

+1 Хорошая идея, звучит как подходящее место для нее! – mikekidder

+0

Cheers Evan, я не думал о том, чтобы вставить заголовки (я не видел вашего сообщения, так спасибо за ссылку) – stooboo

Смежные вопросы