我有一个 ExtJS 4.1 应用程序,它带有一个 Ruby on Rails 3.2 后端,使用 Devise(启用 Timeoutable)进行身份验证、会话管理。
此问题发生在仅通过 SSL 提供应用程序的服务器上。Nginx 将任何非安全请求重定向到 https url。
问题是当设计会话超时时,在我的情况下,在 15 分钟后,任何 AJAX 请求都会被发送/重定向到http://myapp.com/controller?params ,而不是https://myapp.com/controller ?params,就像它通常会做的那样。
我有客户端代码,在非 SSL 设置中可以很好地捕捉潜在的会话过期问题,并重定向到登录页面并显示会话已超时的消息。这是一种基于以下事实的黑客攻击:在会话超时后发出请求时,会返回“无效的 JSON 字符串”错误消息。该错误包含登录页面的 HTML,因为当用户登录时应该是 json 的响应变成了应用程序应该在会话超时时重定向到的登录页面。这段代码在我的Ext.application的启动方法中:
launch: function () {
Ext.Error.handle = function (err) {
$.post('/logs', {message:err.msg});
if (err.msg.indexOf("invalid JSON String") != -1 && err.msg.indexOf("<!DOCTYPE html>") != -1) {
if (err.msg.indexOf("MyApp_Login") != -1)
document.location.href = "/logout?timeout=1";
else
document.location.href = "/logout?error=1";
} else {
gritter(3, "ERROR:", "A client-side error has occurred. If this issue persists, please contact your system administrator.");
if (Ext.isWebKit) console.log(err);
}
}
if (user_signed_in == true) {
Ext.require('MyDesktop.App');
Ext.require('Ext.tab.*');
_myDesktopApp = Ext.create('MyDesktop.App');
Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));
}
}
正如我上面所说,应用程序通过非安全套接字检测到一个控制器请求(或更准确地说是响应),表明会话超时,并采取适当的措施。但是在我的服务器上,通过 SSL,由于某种原因,一旦会话过期,控制器调用最终会通过 http 而不是 https。在 Chrome 中导致这样的错误:
The page at https://server.myapp.com/ displayed insecure content from http://server.app.com/campaign_components_contacts.json?authenticity_token=1vokGHUpsi5w3b3P8mrfUpEGx19hrHJpsCzPayofM7c%3D&campaign_id=2&component_id=2&contact_id=1536&format=json
这可能是 ExtJS 的一个功能,当通过 SSL 检测到问题时它会尝试非安全调用?还是 Rails 的一些特性?我确定两者都不是,只是把我脑海中浮现的一些事情扔掉。
编辑:
通过使用带有--ssl开关的Thin,我已经能够在开发环境中本地测试场景。服务器启动后,我浏览到
https://localhost:3000
没有问题。一旦设计会话到期,任何 json 请求都会触发重定向到登录,正如预期的那样并通过 http 工作。
所以这个问题中描述的问题只出现在我的服务器上,并且可能与我的 NGINX 配置的设置方式有关。
我还将在本地预编译应用程序并使用 prod 环境选项运行,以确保它与 dev 和 prod 之间的区别无关。