使用SPA时,slidingExpiration似乎与使用ASP.NET MVC API无关

时间:2014-10-16 19:55:36

标签: javascript c# asp.net angularjs iis

我的用户在SPA页面上几个小时后就会被注销。但是,如果他们使用较旧的回发表格,他们永远不会超时。所以你有上下文,我已经包含了足够的代码来提供底层问题描述的上下文。

用于身份验证的Web.config

<authentication mode="Forms">
  <forms loginUrl="~/Account/Login" timeout="480" slidingExpiration="true" defaultUrl="~" ticketCompatibilityMode="Framework40"/>
</authentication>

我的api控制器

namespace my.Controllers
{
    public class ApiMotionController : ApiController
    {   
        [Authorize(Roles = "Mover"]
        public IQueryable<Motions> Get()

JavaScript代码

(function () {
'use strict';
angular.module('app')
    .controller('MotionManager', ['$scope', '$http', buildMotionManager]);

function buildMotionManager($scope, $http) {
    /*Static Members*/
    $scope._whoami = 'MotionManager'; //Used for troubleshooting controller

    /*Initialization Code*/
    getMotions($scope, $http)();

    /*Scope methods*/
    $scope.refreshMotionsList = getMotions($scope, $http);
    $scope.addMotion = addMotion($scope, $http);
    $scope.playMotion = playMotion($scope, $http);

}

function getMotions($scope, $http){
    return function(){
        $http.get('/api/getMotions')
             .succeed(function(data){
                 $scope.motionList = data;
             })
             .error(function(data){
                 console.log('FAIL', data);
             });
    };
}

function addMotion($scope, $http){
    //stub. Code not shown here.
};
function playMotion($scope, $http){
    //stub. Code not shown here.
};

})();

上面的代码中存在拼写错误,因为我在清理时将其从原始代码中重新输入。

代码确实按预期工作,但问题是,经过数小时的工作,突然所有的Web API调用都失败了401错误。也就是说,它们都表现得像用户现在已经过验证。

如上所述,当我使用Web表单,甚至是MVC表单并重新发布整个页面时,我无法复制此问题。只有当我使用SPA风格编码时。我没有尝试过其他SPA框架,因为我在这个项目中有6个月的角度定向代码,切换不是一个选项。

我考虑过将一个iframe放在一个定时器中,在后台针对表单对象触发,只是为了欺骗浏览器生成一个正确的表单回发。我想避免这样做,因为它看起来很骇人听闻。

我发现的唯一其他关键问题是我看到一堆schannel错误被记录到IIS服务器上的应用程序事件日志中。它们都是10,10,没有很好的记录。 10系列在10,10之外有很好的记录。但这些建议似乎都不起作用,甚至不相关。

服务器是IIS 7.5,我在IIS 8上试过这个。

应用程序日志错误:

  • 生成致命警报并将其发送到远程端点。这可能导致连接终止。 TLS协议定义的致命错误代码为10. Windows SChannel错误状态为10。
    • 错误状态:10,警报说明:10
  • 生成致命警报并将其发送到远程端点。这可能导致连接终止。 TLS协议定义的致命错误代码为40. Windows SChannel错误状态为1205。
  • 从远程客户端应用程序收到TLS 1.2连接请求,但服务器不支持客户端应用程序支持的任何密码套件。 SSL连接请求失败。

发现

错误代码40表示存在握手问题。由于状态管理是我的平台自定义,我决定将其更改为inproc。到目前为止,我已经看到错误日志减少了新的错误频率,但消失了。但是,我仍在测试401问题。

发布后续跟进

如果重新颁发了证书,并且 schannel 错误已清除,但问题仍然存在。

我已经开始使用细齿梳探索标题信息,即使这意味着我必须在服务器调用时添加自定义标头信息。

我现在已经包含在所有$ http电话withCredentials: true中,这使我的失败率降至15%左右。这意味着每天失败一次或两次。

我开始看着我的#autah&#39;客户端上的cookie,偶尔会发生混乱的事情。 cookie会在没有提示的情况下改变,然后它会改回来。几乎就像会话从当前,到新的,然后回到当前。所以我在服务器上的会话表上杀了我的清理过程,看看我到那里了。

我一直在检查系统日志中的异常或SQL超时,什么都没有。

开始将所有控制器转换为MVC控制器,但是在转换问题之后我遇到了转换问题,包括使用jSON序列化器。当JSON.NET工作得更好时,我仍然不明白决定坚持使用MS序列化器。

当前状态

我做的最后一次更改是将filters.Add(new AuthorizeAttribute());添加到我的FilterConfig.RegisterGlobalFilters函数中。

一切都还在失败。在调查IIS日志后,我仍然看到所有内容都被取消了身份验证。

  • Windows上的FF - 失败
  • Windows上的Chrome - 失败
  • Droid上的Chrome - 失败
  • iPad上的Safari - 失败
  • Windows上的IE浏览器 - 失败

12/10发现

我发现了真正的问题。 MVC控制器中的身份验证与Web API控制器不兼容。因此,当我使用MVC控制器进行身份验证时,Web API控制器基本上会忽略它,并最终超时进行身份验证。

最新发现

显然,当asp.net工作进程关闭并重新启动时,它会得到一个错误的标志,表明数据库模式不存在。所以我删除了支票,所有的读写操作都开始正常。有趣的是,当mvc控制器无法通过身份验证时,api控制器会伪造一个新的cookie。这就像是在创建一个新的提供者实例。但是,我无法找到第二个实例,因此我必须假设现有的提供程序正在重复。

修正正在测试

现在我已经删除了数据库测试,我现在正在测试长期测试中的问题。每次长时间运行都比工作进程保持活动状态长,但比会话超时时间短。

发现此错误的基石

显然,IIS Express隐藏了这个错误,因为它似乎没有外部工作进程。所以我将测试环境移到了本地的IIS服务器上。

1 个答案:

答案 0 :(得分:0)

看起来有几个问题导致了我的问题,每个问题都在这里细分:

  1. IIS Express没有像完整的IIS一样关闭会话。
    1. 所以我将应用程序移动到我的本地IIS,并将日志记录添加到所有内容中。
  2. 每次调用API控制器时,ASP.NET辅助进程都会启动新的提供程序实例。
    1. 这会导致每次调用都进行新的架构检查。 MVC控制器只会在每次初始启动时进行一次检查。
    2. 由于我的提供商与我的应用程序架构结合,我只是禁用了架构检查。
  3. 必须告知Angular编组cookie。
    1. 所以我添加了:cfg: { withCredentials: true, responseType: "json" }
    2. 响应类型是为了涵盖偶尔出现的问题,我会看到文字/文字&#39;。现在我总是看到&application; / json&#39;。这似乎是一个浏览器问题,主要是IE。
  4. 我还必须将config.MapHttpAttributeRoutes();添加到我的WebApiConfig类的register方法中。
  5. 使用所有这些,我发现问题的核心是每个api调用导致我的安全提供程序重新测试模式,我的MVC控制器被设置为在首次加载后抑制该测试。测试总是失败,因为我必须扩展几个表,但我不需要更改模型。

    解决方案:我从提供商处删除了测试。由于提供程序与应用程序的其余部分紧密相关,因此将其视为典型的ASP.NET成员资格提供程序并不合乎逻辑。这是我不需要的顶级功能。

    第二个好处,我获得了一点性能。