里面有两个问题
对于我自己的 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 {
....
}