MVC身份验证和Durandal SPA模板中的Antiforgery令牌

9 浏览
0 Comments

MVC身份验证和Durandal SPA模板中的Antiforgery令牌

我SPA的一些区域需要对所有用户开放,而一些区域需要进行身份验证。在这些区域中,我想要保护通过AJAX加载的数据。\n我有一个身份验证服务(见下文),我将其作为依赖项添加到我的durandal的main.js中。该服务被称为:\nauthentication\n在我的main.js中,我调用\nauthentication.handleUnauthorizedAjaxRequest(function () {\n app.showMessage(\'You are not authorized, please login\')\n .then(function () {\n router.navigateTo(\'#/user/login\');\n });\n});\n它会警告用户他们未经授权,并将用户导航到登录视图/视图模型,用户可以在其中输入详细信息并尝试登录。\n在构建此身份验证视图模型时,会有一些问题需要考虑:\n- 我所做的事情是否存在明显的问题?\n- 这是我在Durandal中应该做的方式吗?\n- 我是在重新发明轮子吗?我在Durandal中找不到类似的东西。\n大多数人似乎都创建了单独的cshtml页面;一个用于登录(如果用户未经身份验证),另一个是常规的index.cshtml。对我来说,是否有任何好的理由转换到这种方法?\n我的服务器端“用户控制器”的登录操作具有[ValidateAntiForgeryToken]属性,我需要将其发送出去。\n我还有一个“antiforgery”服务(见下文),我还将其作为依赖项添加到我的main.js视图模型文件中\n然后(也在我的main.js中)。\nantiforgery.addAntiForgeryTokenToAjaxRequests();\n这会拦截所有ajax请求(以及内容),并将MVC AntiForgeryToken值添加到数据中。\n看起来正是我想要的。如果有任何错误/错误,请告诉我。\n完整的身份验证服务如下。\n// services/authentication.js\ndefine(function (require) {\n var system = require(\'durandal/system\'),\n app = require(\'durandal/app\'),\n router = require(\'durandal/plugins/router\');\n return {\n handleUnauthorizedAjaxRequests: function (callback) {\n if (!callback) {\n return;\n }\n $(document).ajaxError(function (event, request, options) {\n if (request.status === 401) {\n callback();\n }\n });\n },\n canLogin: function () { \n return true;\n },\n login: function (userInfo, navigateToUrl) {\n if (!this.canLogin()) {\n return system.defer(function (dfd) {\n dfd.reject();\n }).promise();\n }\n var jqxhr = $.post(\"/user/login\", userInfo)\n .done(function (data) {\n if (data.success == true) {\n if (!!navigateToUrl) {\n router.navigateTo(navigateToUrl);\n } else {\n return true;\n }\n } else {\n return data;\n }\n })\n .fail(function (data) {\n return data;\n });\n return jqxhr;\n }\n };\n});\n// services/antiforgery.js\ndefine(function (require) {\n var app = require(\'durandal/app\');\n return {\n /* this intercepts all ajax requests (with content)\n and adds the MVC AntiForgeryToken value to the data\n so that your controller actions with the [ValidateAntiForgeryToken] attribute won\'t fail\n original idea came from http://stackoverflow.com/questions/4074199/jquery-ajax-calls-and-the-html-antiforgerytoken\n to use this\n 1) ensure that the following is added to your Durandal Index.cshml\n

\n @Html.AntiForgeryToken()\n

\n 2) in main.js ensure that this module is added as a dependency\n 3) in main.js add the following line\n antiforgery.addAntiForgeryTokenToAjaxRequests();\n */\n addAntiForgeryTokenToAjaxRequests: function () {\n var token = $(\'#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]\').val();\n if (!token) {\n app.showMessage(\'ERROR: Authentication Service could not find __RequestVerificationToken\');\n }\n var tokenParam = \"__RequestVerificationToken=\" + encodeURIComponent(token);\n $(document).ajaxSend(function (event, request, options) {\n if (options.hasContent) {\n options.data = options.data ? [options.data, tokenParam].join(\"&\") : tokenParam;\n }\n });\n }\n };\n});

0
0 Comments

在Durandal SPA模板中,MVC认证和防伪标记(MVC Authentication and Antiforgery token)的问题出现的原因是希望将防伪标记(antiforgery token)放在请求头(header)中,这样可以方便地在服务器端解析请求,而不需要与表单数据混合在一起。

解决方法是创建一个自定义的操作过滤器(action filter)来检查防伪标记。可以参考Evan在此处的回答中提供的解决方法。

在该的问题中,Evan提到了将防伪标记放在请求头中的方法,并提供了一个链接供参考。其他回答者也表示感谢Evan提供的链接,并表示之前没有考虑过将防伪标记放在请求头中这种方法。

以上是关于Durandal SPA模板中MVC认证和防伪标记问题的原因和解决方法的整理。

0