使用play框架强制登录Https路由以进行登录

时间:2011-09-14 10:44:27

标签: security login routing https playframework

我想仅针对我的应用程序的登录页面强制执行https路由。

Play可以这样做吗!没有使用前端http服务器?

6 个答案:

答案 0 :(得分:21)

即使用户直接键入http://,您也可以使用@Before拦截器重定向每个请求。下面是我使用的代码(它在运行无容器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's 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's 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;
            }
        }
    }    
}

答案 1 :(得分:6)

这是一个适用于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。

e.g。

@With(ForceHttps.class)
public class HttpsController extends Controller {

}

答案 2 :(得分:3)

我认为您可以在控制器中检查request.secure == true然后重定向到https。

答案 3 :(得分:3)

如果您使用AWS,则可以在Load Balancer中终止HTTPS并使用过滤器将HTTP连接重定向到HTTPS。

AWS Conf:

443(负载均衡器)----------&gt; 80(服务器)

80(负载均衡器)----------&gt; 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)
        }
    }
}

答案 4 :(得分:2)

你应该可以。执行以下操作:

  1. 在application.config文件中设置http.port和https.port
  2. 用户@@ {Controller.action()。secure()}当您需要指向安全页面时。同时使用@@生成完整URL(包括https)并提示安全提示播放您想要的HTTPS协议
  3. 这应该有效

答案 5 :(得分:0)

从控制器的角度来看似乎不可能。从模板Pere解决方案可以工作,但这只会从模板生成https网址。

如果用户通过手动输入或跟踪http url的链接来访问登录操作,则似乎没有办法强制/重定向到https。

最好的方式似乎是有一个前端代理。