Я хочу использовать https-маршрутизацию для страницы входа только моего приложения.
Можно ли это сделать в Play! без использования HTTP-сервера переднего конца?
Я хочу использовать https-маршрутизацию для страницы входа только моего приложения.
Можно ли это сделать в Play! без использования HTTP-сервера переднего конца?
Вы можете использовать перехватчик @Before
для перенаправления каждого запроса, даже если пользователь напрямую набирает http://. Ниже приведен код, который я использую (он работает при запуске без контейнера play run
или при запуске за передним концом, например, на Heroku).
public class HttpsRequired extends Controller {
/** Called before every request to ensure that HTTPS is used. */
@Before
public static void redirectToHttps() {
//if it not secure, but Heroku has already done the SSL processing then it might actually be secure after all
if (!request.secure && request.headers.get("x-forwarded-proto") != null) {
request.secure = request.headers.get("x-forwarded-proto").values.contains("https");
}
//redirect if it not secure
if (!request.secure) {
String url = redirectHostHttps() + request.url;
System.out.println("Redirecting to secure: " + url);
redirect(url);
}
}
/** Renames the host to be https://, handles both Heroku and local testing. */
@Util
public static String redirectHostHttps() {
if (Play.id.equals("dev")) {
String[] pieces = request.host.split(":");
String httpsPort = (String) Play.configuration.get("https.port");
return "https://" + pieces[0] + ":" + httpsPort;
} else {
if (request.host.endsWith("domain.com")) {
return "https://secure.domain.com";
} else {
return "https://" + request.host;
}
}
}
}
Вот пример, который работает с Java Play 2.1.1 и Heroku.
public class ForceHttps extends Action<Controller> {
// heroku header
private static final String SSL_HEADER = "x-forwarded-proto";
@Override
public Result call(Context ctx) throws Throwable {
final Result result;
if (Play.isProd() && !isHttpsRequest(ctx.request())) {
result = redirect("https://" + ctx.request().host()
+ ctx.request().uri());
}
else {
// let request proceed
result = this.delegate.call(ctx);
}
return result;
}
private static boolean isHttpsRequest(Request request) {
// heroku passes header on
return request.getHeader(SSL_HEADER) != null
&& request.getHeader(SSL_HEADER)
.contains("https");
}
}
Затем для любых контроллеров, которые вы хотите проверить для https, добавьте @With (ForceHttps.class). Или, если вы хотите, чтобы все контроллеры проверялись, добавьте класс HttpsController extends Controller и все ваши классы расширят HttpsController.
например.
@With(ForceHttps.class)
public class HttpsController extends Controller {
}
Я думаю, что вы можете проверить контроллер для request.secure == true, а затем перенаправить на https.
Если вы используете AWS, вы можете завершить HTTPS на балансировщике нагрузки и использовать фильтр для перенаправления HTTP-соединения на HTTPS.
AWS Conf:
443 (Балансировщик нагрузки) ---------- > 80 (Сервер)
80 (Балансировщик нагрузки) ---------- > 80 (Сервер)
Фильтр:
object HTTPSRedirectFilter extends Filter with Logging {
def apply(nextFilter: (RequestHeader) => Future[SimpleResult])(requestHeader: RequestHeader): Future[SimpleResult] = {
//play uses lower case headers.
requestHeader.headers.get("x-forwarded-proto") match {
case Some(header) => {
if ("https" == header) {
nextFilter(requestHeader).map { result =>
result.withHeaders(("Strict-Transport-Security", "max-age=31536000"))
}
} else {
Future.successful(Results.Redirect("https://" + requestHeader.host + requestHeader.uri, 301))
}
}
case None => nextFilter(requestHeader)
}
}
}
Ты должен уметь. Выполните следующие действия:
Это должно работать
Это не кажется возможным с точки зрения контроллера. Из шаблона решение Pere работает, но это только генерирует https-url из шаблона.
Если пользователь обращается к действию входа в систему, либо набрав вручную, либо следуя ссылке на http-url, похоже, нет способа принудительного/перенаправления на https.
Лучший способ, похоже, имеет прокси-сервер.