代码之家  ›  专栏  ›  技术社区  ›  Cyril N.

PlayFramework在http而不是httpS中返回绝对url?

  •  3
  • Cyril N.  · 技术社区  · 10 年前

    我在Play中实施了一个项目!仅使用https的NGinx框架。

    一切都很好,SSL得到了很好的认可,我可以在任何地方使用我的应用程序,但在Play!返回一个绝对URL,它是http,而不是https。

    这是有问题的,我不知道问题在哪里。 我尝试使用-Dhttp.port=XXXX而不是-Dhttp.pport=XXXX来启动Play,但它没有更改“http”而不是“https”的输出。

    我怀疑Nginx配置错误(我忘记了一个参数?)。 这是我的 sites-enabled/website 配置文件:

    proxy_buffering    off;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Scheme "https"; # I also tried $scheme without any luck
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   Host $http_host;
    proxy_http_version 1.1;
    
    server {
            listen 80;
            server_name my.website.com;
            return      301 https://my.website.com;
    }
    
    upstream my-backend {
            server 127.0.0.1:9100;
    }
    
    server {
        listen               443;
        ssl                  on;
        root                 /var/www/website/errors/;
    
        # http://www.selfsignedcertificate.com/ is useful for development testing
        ssl_certificate      /etc/nginx/ssl/my.website.com.crt;
        ssl_certificate_key  /etc/nginx/ssl/my.website.com.key;
    
        # From https://bettercrypto.org/static/applied-crypto-hardening.pdf
        ssl_prefer_server_ciphers on;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # not possible to do exclusive
        ssl_ciphers 'EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA';
        add_header Strict-Transport-Security max-age=15768000; # six months
        # use this only if all subdomains support HTTPS!
        # add_header Strict-Transport-Security "max-age=15768000; includeSubDomains"
    
        keepalive_timeout    70;
        server_name my.website.com;
    
        location / {
            #proxy_pass  http://my-backend;
            proxy_pass  http://127.0.0.1:9100;
        }
    
        location ~ /\.git {
            deny all;
        }
    
        error_page 502 @maintenance;
        location @maintenance {
            rewrite ^(.*)$ /error502.html break;
        }
    }
    

    我错过了什么?

    使现代化 :以下是生成绝对url的代码:

    controllers.routes.Pages.loginToken(getToken()).absoluteURL(play.mvc.Http.Context.current().request());
    
    2 回复  |  直到 10 年前
        1
  •  7
  •   Community CDub    3 年前

    您实际需要的是在 X-Forwarded-Proto 标题。没有 X-Forwarded-* 标头是标准的,但惯例(或实际标准)是将方案放入 X-前向协议 ,而Play从2.3.0开始支持此功能:

    https://github.com/playframework/playframework/pull/1823

    因此,如果您在nginx配置中添加以下内容:

    proxy_set_header   X-Forwarded-Proto $scheme;
    

    并通过将此添加到您的 application.conf :

    trustxforwarded=true
    

    然后 RequestHeader.secure 将返回true。

    请注意,在Play 2.4中,我们显著改进了支持,实现了新标准的完整规范 Forwarded header ,以及能够指定要信任来自哪些主机的转发标头。

        2
  •  6
  •   Michael Zajac    10 年前

    有几个重载 absoluteURL 。您正在使用这个:

    public String absoluteURL(Http.Request request) {
        return absoluteURL(request.secure(), request.host());
    }
    

    问题是,由于您通过nginx反向代理Play,因此Play实际上是通过HTTP而不是HTTPS接收所有请求。这意味着 request.secure() 为假,且 绝对URL 将返回包含 http://... .

    而是手动设置 secure true 在其中一个重载中:

    controllers.routes.Pages.loginToken(getToken()).absoluteURL(play.mvc.Http.Context.current().request(), true);
    

    此外,我通常做的是为 保护 因此它可以在本地开发时生成非https URL。

    在application.conf中:

    application.secure = false # for local dev
    

    在生产中,我添加了命令行选项 -Dapplication.secure=true 启动应用程序时,重写 application.conf .

    然后生成URL如下所示:

    controllers.routes.Pages.loginToken(getToken()).absoluteURL(
        play.mvc.Http.Context.current().request(), 
        play.Play.application().configuration().getBoolean("application.secure", true) // default to true
    );