使用Durandal SPA模板的MVC身份验证和防伪令牌

我的SPA的某些区域需要向所有用户开放,某些区域需要身份验证。在这些方面,我想保护的是通过AJAX加载的数据

我有一个身份验证服务(见下文),我将其作为依赖项添加到durandalmain.js中。该服务称为:

身份验证

在mymain.js中,我调用

身份验证。handleunauthoritizedajaxRequest(函数(){
app.showMessage('您未经授权,请登录')
.然后(函数(){
router.navigateTo(“#/user/login”);
});
});

它警告用户他们未获得授权,并将用户导航到登录视图/视图模型,用户可以在其中输入详细信息并尝试登录

构建此验证视图模型时会想到一些问题:

  • 我在做什么有什么明显的顾虑吗
  • 这就是我在Durandal做事情的方式吗
  • 我是在重新发明轮子吗?我在杜兰达尔身上看不到这样的东西

大多数人似乎在创建独立的cshtml页面;一个用于登录(如果用户未通过身份验证),以及通常的index.cshtml有什么好的理由让我切换到该方法吗

我在服务器端“用户控制器”上的登录操作具有[ValidateAntiForgeryToken]属性,我也需要发送该属性。
我还有一个“Antifforgery”服务(见下文),我还将其作为依赖项添加到我的main.jsviewModel文件中
然后(也是在我的main.js中)

antiforgery.addantiforgerytoketoajaxrequests();

这将拦截所有ajax请求(以及内容),并将MVC AntiForgeryToken值添加到数据中。
看起来就像我想要的那样。如果有任何错误,请告诉我

完成下面的身份验证服务

//服务/authentication.js
定义(功能(要求){
var系统=需要('durandal/system'),
app=require('durandal/app'),
路由器=require('durandal/插件/路由器');
返回{
handleUnauthorizedAjaxRequests:函数(回调){
如果(!回调){
回来
}
$(文档).ajaxError(函数(事件、请求、选项){
if(request.status==401){
回调();
}
});
},
canLogin:function(){
返回true;
},
登录:函数(userInfo、navigateToUrl){
如果(!this.canLogin()){
返回系统延迟(功能(dfd){
拒绝();
}).promise();
}
var jqxhr=$.post(“/user/login”,userInfo)
.完成(功能(数据){
if(data.success==true){
如果(!!导航URL){
路由器.navigateTo(navigateToUrl);
}否则{
返回true;
}
}否则{
返回数据;
}
})
.失败(功能(数据){
返回数据;
});
返回jqxhr;
}
};
});
//服务/antiforgery.js
定义(功能(要求){
var app=要求('durandal/app');
返回{
/*这将拦截所有ajax请求(包括内容)
并将MVC AntiForgeryToken值添加到数据中
这样,具有[ValidateAntiForgeryToken]属性的控制器操作不会失败
最初的想法来自http://stackoverflow.com/questions/4074199/jquery-ajax-calls-and-the-html-antiforgerytoken
用这个
1) 确保将以下内容添加到Durandal Index.cshml中
<form id=“uu AjaxAntiForgeryForm”action=“#”method=“post”>
@Html.AntiForgeryToken()
</form>
2) 在main.js中,确保此模块作为依赖项添加
3) 在main.js中添加以下行
addAntiForgeryTokenToAjaxRequests();
*/
addAntiForgeryTokenToAjaxRequests:函数(){
var-token=$('#uuu AjaxAntiForgeryForm输入[name=uu-RequestVerificationToken]')。val();
如果(!令牌){
app.showMessage('错误:身份验证服务找不到u RequestVerificationToken');
}
var tokenParam=“\uuu RequestVerificationToken=“+encodeURIComponent(令牌);
$(文档).ajaxSend(函数(事件、请求、选项){
if(options.hasContent){
options.data=options.data?[options.data,tokenParam]。加入(“&”):tokenParam;
}
});
}
};
});

我更喜欢在标题中传递防伪令牌。这种方式很容易解析出服务器上的请求,因为它不会与表单的数据混合在一起

然后我创建了一个自定义操作过滤器来检查antiforgery令牌

我已经写了一篇关于如何做到这一点的帖子

发表评论