【发布时间】:2013-03-27 14:47:39
【问题描述】:
我的 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');
});
});
它警告用户他们没有被授权,并将用户导航到登录视图/视图模型,他们可以在其中输入详细信息并尝试登录。
构建此身份验证视图模型时想到的一些问题:
- 我正在做的事情有什么明显的顾虑吗?
- 这就是我在 Durandal 的“本意”做事的方式吗?
- 我是在重新发明轮子吗?我在 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, request, options) {
if (options.hasContent) {
options.data = options.data ? [options.data, tokenParam].join("&") : tokenParam;
}
});
}
};
});
【问题讨论】:
-
嗨 Stuart,你的想法很棒,我正在尝试将它应用到我的 Hot Towel/Durandal 项目中。我获得了身份验证和防伪服务,但我没有获得身份验证服务来拦截未经授权的用户并将他们重定向到登录页面。我怎么做?我需要向 Index.cshtml 添加一些内容吗?谢谢
-
这也在 DurandalJs Google Group 上 - 那里有其他人的更新,我还添加了一些代码示例 - 它们不会真正适合这里的评论......所以;- ) .. 这是链接groups.google.com/forum/?hl=en&fromgroups=#!topic/…
标签: jquery asp.net-mvc durandal