我的SPA的一些区域需要对所有用户开放,并且一些区域需要认证。在这些区域,它是通过AJAX加载的数据,我想保护。
我有一个认证服务(见下面),我添加作为依赖项在我的durandal main.js。服务被调用:
authentication
在我的main.js我调用
authentication.handleUnauthorizedAjaxRequest(function () { app.showMessage('You are not authorized,please login') .then(function () { router.navigateTo('#/user/login'); }); });
它警告用户他们没有被授权,并导航用户到登录视图/ viewmodel他们可以输入详细信息,并尝试登录。
构建此身份验证视图时出现的一些问题模型:
>有什么明显的问题,我在做什么?
>这是我怎么’意味着’在杜兰达尔做事情?
>我是重新发明轮子吗?我在Durandal看不到这样的东西。
大多数人似乎创建单独的cshtml页面;一个用于登录(如果用户未认证),和通常的index.cshtml有什么好的理由我切换到该方法?
我的登录操作在我的服务器端’用户控制器’有我需要发送的[ValidateAntiForgeryToken]属性。
我也有一个“反保护”服务(见下文),我也添加为一个依赖项在我的main.js viewmodel文件
然后(也在我的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,options) { if (options.hasContent) { options.data = options.data ? [options.data,tokenParam].join("&") : tokenParam; } }); } }; });
解决方法
我喜欢通过防御标记在标题。这样,它很容易解析出在服务器上的请求,因为它没有与您的表单的数据混合。
然后,我创建了一个自定义操作过滤器来检查防御令牌。
我created a post已经在如何做到这一点。