将部署在Heroku的Scala/PlayFramework应用强制重定向至HTTPS
嘿,我来帮你搞定这个问题!你用的是Scala开发的Play Framework应用,部署在Heroku上,和PHP依赖.htaccess的逻辑不一样,咱们得用Play本身的特性来实现HTTP强制转HTTPS,具体两种方法任你选:
实现Play Framework(Scala)在Heroku上强制HTTPS跳转
方法一:用Play内置配置(推荐,简单省心)
从Play 2.6版本开始,官方就支持直接通过配置文件开启强制HTTPS跳转,你只需要修改conf/application.conf,添加这两行配置:
# 开启所有请求到HTTPS的跳转 play.filters.https.redirectEnabled = true # 信任Heroku反向代理传递的X-Forwarded-Proto头(关键!) play.filters.https.trustXForwardedProto = true
为啥要加第二行?因为Heroku的请求都是通过反向代理转发到你的应用的,真实的请求协议是通过X-Forwarded-Proto这个HTTP头传递的,Play默认不会信任这个头,所以必须开启这个配置才能正确识别请求是HTTP还是HTTPS。
方法二:自定义过滤器(适合需要额外逻辑的场景)
如果你的Play版本比较旧,或者需要添加比如特定路径不跳转这类自定义逻辑,可以自己写个过滤器:
- 在项目里创建
app/filters/ForceHttpsFilter.scala文件,代码如下:
import play.api.mvc._ import scala.concurrent.ExecutionContext import javax.inject.Inject class ForceHttpsFilter @Inject()(val mat: Materializer, ec: ExecutionContext) extends Filter { override def apply(nextFilter: RequestHeader => Future[Result])(requestHeader: RequestHeader): Future[Result] = { // 读取Heroku传递的X-Forwarded-Proto头判断是否为HTTPS val isHttps = requestHeader.headers.get("X-Forwarded-Proto").contains("https") // 本地开发不跳转,线上非HTTPS请求则重定向 if (!isHttps && requestHeader.host != "localhost") { val httpsUrl = s"https://${requestHeader.host}${requestHeader.uri}" Future.successful(Results.MovedPermanently(httpsUrl)) } else { nextFilter(requestHeader) } } }
- 接着在
conf/application.conf里注册过滤器:
play.http.filters = "filters.Filters"
- 最后创建
app/filters/Filters.scala,把自定义过滤器和Play默认的过滤器整合起来:
import javax.inject.Inject import play.api.http.DefaultHttpFilters import play.filters.csrf.CSRFFilter import play.filters.headers.SecurityHeadersFilter class Filters @Inject()( csrfFilter: CSRFFilter, securityHeadersFilter: SecurityHeadersFilter, forceHttpsFilter: ForceHttpsFilter ) extends DefaultHttpFilters(csrfFilter, securityHeadersFilter, forceHttpsFilter)
重要提醒
别再折腾.htaccess啦!Play Framework是基于JVM的应用,在Heroku上运行的是Play的内置服务器,根本不会读取Apache的.htaccess文件,那套规则对你的应用完全不生效哦。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

