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

Cyr*_* N. 3 java nginx playframework playframework-2.2

我在仅使用https的NGinx的Play!Framework中实现了一个项目.

一切正常,SSL是公认的,我可以在任何地方使用我的应用程序,但播放时!返回绝对URL,它是http,而不是https.

这是有问题的,我不知道问题出在哪里.我尝试使用-Dhttps.port = XXXX而不是-Dhttp.port = 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

更新:这是生成绝对URL的代码:

controllers.routes.Pages.loginToken(getToken()).absoluteURL(play.mvc.Http.Context.current().request());
Run Code Online (Sandbox Code Playgroud)

Jam*_*per 7

您实际需要的是在X-Forwarded-Proto标题中添加方案.没有X-Forwarded-*标题是标准的,但约定(或事实标准)是将方案放入X-Forwarded-Proto,并且Play自2.3.0以来支持此:

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

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

proxy_set_header   X-Forwarded-Proto $scheme;
Run Code Online (Sandbox Code Playgroud)

并已将Play配置为信任x转发的标头,方法是将其添加到您的application.conf:

trustxforwarded=true
Run Code Online (Sandbox Code Playgroud)

然后RequestHeader.secure将返回true.

请注意,在Play 2.4中,我们已经大大改进了支持,实现了新标准Forwarded的完整规范,并且能够指定哪些主机信任转发头.

  • 随着游戏2.4,播放配置似乎与play.http.forwarded.trustedProxies&play.http.forwarded.version(更多信息以做[的httpserver /配置信任代理(https://www.playframework.com/documentation/2.4 .x/HTTPServer #configure-trusted-proxies)) (2认同)

Mic*_*jac 5

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

public String absoluteURL(Http.Request request) {
    return absoluteURL(request.secure(), request.host());
}
Run Code Online (Sandbox Code Playgroud)

问题在于,由于您是通过nginx反向代理到Play的,因此Play实际上是通过HTTP而不是HTTPS接收所有请求的。这表示该request.secure()值为false,absoluteURL并将返回包含的URL http://...

而是手动将其设置securetrue重载之一:

controllers.routes.Pages.loginToken(getToken()).absoluteURL(play.mvc.Http.Context.current().request(), true);
Run Code Online (Sandbox Code Playgroud)

另外,我通常要做的是使用一个配置变量,secure以便在本地开发时可以生成非https URL。

在application.conf中:

application.secure = false # for local dev
Run Code Online (Sandbox Code Playgroud)

在生产环境中,我-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
);
Run Code Online (Sandbox Code Playgroud)

  • 自2.3.0起,Play的`request.secure()`就支持`X-Forwarded-Proto`标头,因此只要您正确配置了所有内容,`absoluteURL`就会返回一个https URL。 (2认同)