我的用户在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上试过这个。
应用程序日志错误:
发现
错误代码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日志后,我仍然看到所有内容都被取消了身份验证。
12/10发现
我发现了真正的问题。 MVC控制器中的身份验证与Web API控制器不兼容。因此,当我使用MVC控制器进行身份验证时,Web API控制器基本上会忽略它,并最终超时进行身份验证。
最新发现
显然,当asp.net工作进程关闭并重新启动时,它会得到一个错误的标志,表明数据库模式不存在。所以我删除了支票,所有的读写操作都开始正常。有趣的是,当mvc控制器无法通过身份验证时,api控制器会伪造一个新的cookie。这就像是在创建一个新的提供者实例。但是,我无法找到第二个实例,因此我必须假设现有的提供程序正在重复。
修正正在测试
现在我已经删除了数据库测试,我现在正在测试长期测试中的问题。每次长时间运行都比工作进程保持活动状态长,但比会话超时时间短。
发现此错误的基石
显然,IIS Express隐藏了这个错误,因为它似乎没有外部工作进程。所以我将测试环境移到了本地的IIS服务器上。
答案 0 :(得分:0)
看起来有几个问题导致了我的问题,每个问题都在这里细分:
cfg: { withCredentials: true, responseType: "json" }
config.MapHttpAttributeRoutes();
添加到我的WebApiConfig类的register方法中。使用所有这些,我发现问题的核心是每个api调用导致我的安全提供程序重新测试模式,我的MVC控制器被设置为在首次加载后抑制该测试。测试总是失败,因为我必须扩展几个表,但我不需要更改模型。
解决方案:我从提供商处删除了测试。由于提供程序与应用程序的其余部分紧密相关,因此将其视为典型的ASP.NET成员资格提供程序并不合乎逻辑。这是我不需要的顶级功能。
第二个好处,我获得了一点性能。