2

我有一个 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 之间的区别无关。

4

1 回答 1

2

哇,原来与设计会话超时、Rails 或 ExtJS 无关。

最终通过调整 NGINX 配置解决了这个问题,根据文档,这对于所使用的版本应该是正确的,但结果却导致了这个问题。

当前的 ssl 服务器位:

server {
            listen 443;
            ssl on;
            ssl_certificate      /srv/ssl/server.myapp.com.combined.crt;
            ssl_certificate_key  /srv/ssl/server.myapp.com.key;
            server_name server.myapp.com;
            root /var/www/myapp/current/public;
            passenger_enabled on;
            rails_env myapp_staging;
    }

在我有之前:

server {
            listen 443 ssl;
            ssl_certificate      /srv/ssl/server.myapp.com.combined.crt;
            ssl_certificate_key  /srv/ssl/server.myapp.com.key;
            server_name server.myapp.com;
            root /var/www/myapp/current/public;
            passenger_enabled on;
            rails_env myapp_staging;
    }

区别在于分手

listen 443 ssl;

进入:

listen 443;
ssl on;
于 2012-12-28T07:20:07.973 回答