【问题标题】:Play framework redirect HTTP to https播放框架将 HTTP 重定向到 https
【发布时间】:2014-10-15 01:54:34
【问题描述】:

我使用播放框架版本 2.2.3 并使用以下命令运行激活器以使用 https 访问站点。

./activator run  -Dhttp.port=disabled  -Dhttps.port=9043

我在浏览器中输入如下网址

https://localhost:9043/signin

然后它工作正常并重定向到 https。但问题是当我如下更改我的网址时

http://localhost:9043/signin

那我想把上面的 URL 重定向到 https,这个在 play framework 中应该如何处理?

【问题讨论】:

    标签: playframework playframework-2.3


    【解决方案1】:

    里面有两个问题

    • 我们如何在 Play 中检测 SSL?

    对于我自己的 Play 2.2,我使用反向代理来处理 SSL,它会自动添加请求标头“X-Forwarded-Proto”。然后我检查该标头以验证连接是通过 SSL 进入的。

        String protocolHeaders = context.request().getHeader("X-Forwarded-Proto");
        if(protocolHeaders != null) {
            String[] split = protocolHeaders.split(",");
            for(int i=0;i<split.length;i++) {
                if(split[i].trim().equalsIgnoreCase("https")) {
                    return delegate.call(context);
                }
            }
        }
    

    我可以选择升级 Play,Play 2.3 https 检测是自动的,标头类有一个内置的 secure() 方法,可以检测 SSL 并处理反向代理 SSL。

    https://www.playframework.com/documentation/2.3.x/api/java/play/mvc/Http.RequestHeader.html#secure()

    • 如何处理将不安全 (http) 请求重定向到安全 (https) 的问题?

    我使用了一个动作,我用它来注释我的控制器(或基本控制器)。

    public class SslEnforcerAction  extends play.mvc.Action<SslEnforced>  {
    
    
        @Override
        public Promise<SimpleResult> call(Context context) throws Throwable {
    
            Logger.info("Running ssl enforcer");
    
            String sslEnabled = Play.application().configuration().getString("app.ssl.enabled");
            if(!StringUtils.equals(sslEnabled, "true")) {
                return delegate.call(context);
            }
    
            Logger.info("X-Forwarded-Proto : {}", context.request().getHeader("X-Forwarded-Proto"));
    
            String protocolHeaders = context.request().getHeader("X-Forwarded-Proto");
            if(protocolHeaders != null) {
                String[] split = protocolHeaders.split(",");
                for(int i=0;i<split.length;i++) {
                    if(split[i].trim().equalsIgnoreCase("https")) {
                        return delegate.call(context);
                    }
                }
            }
    
            Controller.flash("success", "For your security we've switched to SSL");
    
            String target = "";
            if(configuration.response() == SslEnforcedResponse.SELF) {
                target = "https://" + context.request().host() + context.request().uri();
            }
            else {
                target = controllers.my.dashboard.routes.DashboardController.index().absoluteURL(true, context._requestHeader());
            }
            //if we are here then ssl is enabled and the request wasn't ssl, so reject them
            return Promise.pure(Controller.redirect(target));
        }
    }
    
    
    
    /** allow controllers to send insure requests to themselves to dashboard */
    public enum SslEnforcedResponse {
    
        SELF,
        DASHBOARD
    }
    
    
    @With(SslEnforcerAction.class)
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface SslEnforced {
       SslEnforcedResponse response() default SslEnforcedResponse.SELF;
    }
    
    
    
    @SslEnforced
    public class Application extends Controller {
        ....
    }
    

    【讨论】:

    • 您好,使用 ./activator run -Dhttp.port=disabled -Dhttps.port=9043 运行激活器这个命令是否正确?
    • 还有一件事我希望它能够在没有任何负载平衡器或反向代理的情况下工作。
    • 如果您可以加载 https,这意味着它可以正常工作,挑战在于让应用程序检测浏览器请求页面的协议。在 Play 2.2 中没有我知道的方法,这就是为什么反向代理是一个很好的解决方案。我知道的就这么多了。
    【解决方案2】:

    对于我们这些运行 Play 2.5 并在 4 年后继续登陆此页面的人:

    在 build.sbt 中添加:

    libraryDependencies += "com.github.enalmada" %% "play-https-redirect" % "1.0.2"
    

    在 app/ 文件夹中创建一个 Filters.java 文件。以下示例重定向并压缩响应,如果需要,您可以删除 Gzip 位:

    import com.github.enalmada.filters.HttpsRedirectFilter;
    import play.filters.gzip.GzipFilter;
    import play.http.HttpFilters;
    import play.mvc.EssentialFilter;
    
    import javax.inject.Inject;
    
    public class Filters implements HttpFilters {
    
    private EssentialFilter[] filters;
    
    @Inject
    public Filters(GzipFilter gzipFilter, HttpsRedirectFilter httpsRedirectFilter) {
        filters = new EssentialFilter[] { gzipFilter.asJava(),  httpsRedirectFilter.asJava()};
    }
    
    public EssentialFilter[] filters() {
        return filters;
    }
    

    }

    在application.conf,根级别,添加:

    httpsRedirect {
      enabled=true
      modes=["Prod", "Dev"]
      excluded=["/url-to-exclude"]
      hsts {
         enabled=true
         maxAge=31536000
         preload = true
         includeSubDomains = true
      }
    }
    
    play.filters.enabled += play.filters.https.RedirectHttpsFilter
    

    下载 play-https-redirect example project 并查看它在您的本地主机中的工作。

    【讨论】:

      【解决方案3】:

      从 play 2.6.x 开始,它现在由 configuration 支持

      play.filters.enabled += play.filters.https.RedirectHttpsFilter
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-01
        • 2017-11-05
        • 2013-02-16
        • 1970-01-01
        • 2017-11-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多