Как заставить SSL на некоторых URL-адресах с помощью рестлета на Heroku - PullRequest
1 голос
/ 05 февраля 2012

У меня есть приложение на основе restlet, работающее на heroku, и я хочу использовать SSL.Я включил базовую опцию "piggyback" ssl, поэтому он принимает соединения ssl - почти там!Тем не менее, я хочу, чтобы некоторые (на самом деле, вероятно, все) URL работали, только если пользователь подключается через ssl.Как сейчас (мне сказали), Heroku преобразует SSL в вызовы не-ssl и устанавливает HTTP_X_FORWARDED_PROTO на https, так что я думаю, что мне нужно разобраться с этим в рестлете, но я не уверен, как.Я вижу класс Redirector, но мне не ясно, могу ли я использовать этот класс для решения этой проблемы.

Примечание. Ранее я запускал свое приложение с использованием GAE, в котором использовался контейнер сервлета, поэтому я мог указать«КОНФИДЕНЦИАЛЬНО» в web.xml.

Спасибо!

1 Ответ

2 голосов
/ 06 февраля 2012

Вы можете получить информацию из заголовков HTTP-запроса и затем решить, хотите ли вы выдать ошибку или перенаправить:

    Form requestHeaders = (Form) this.getRequest().getAttributes().get("org.restlet.http.headers");

    boolean secure = false;
    if (requestHeaders.getValues("x-forwarded-proto") != null) {
        secure = requestHeaders.getValues("x-forwarded-proto").contains("https");
    }

Расширяя это, вы можете создать Фильтр, который можно легко применить к маршруту. Полный пример кода: на GitHub . Но вот основной SecureFilter:

public class SecureFilter extends Filter {

    private boolean doRedirect;

    public SecureFilter(Context context, Restlet next) {
        super(context);
        doRedirect = false;
        setNext(next);
    }

    public SecureFilter(Context context, Restlet next, boolean doRedirect) {
        super(context);
        this.doRedirect = doRedirect;
        setNext(next);
    }

    public SecureFilter(Context context, Class<?> next) {
        super(context);
        doRedirect = false;
        setNext(next);
    }

    public SecureFilter(Context context, Class<?> next, boolean doRedirect) {
        super(context);
        this.doRedirect = doRedirect;
        setNext(next);
    }

    public boolean isDoRedirect() {
        return doRedirect;
    }

    public void setDoRedirect(boolean doRedirect) {
        this.doRedirect = doRedirect;
    }

    @Override
    protected int beforeHandle(Request request, Response response) {
        Form requestHeaders = (Form) request.getAttributes().get("org.restlet.http.headers");

        if ((requestHeaders.getValues("x-forwarded-proto") != null) && (requestHeaders.getValues("x-forwarded-proto").indexOf("https") != 0)) {
            if (doRedirect) {
                String target = "https://" + request.getHostRef().getHostDomain() + request.getResourceRef().getPath();
                Redirector redirector = new Redirector(getContext(), target, Redirector.MODE_CLIENT_SEE_OTHER);
                redirector.handle(request, response);
                return STOP;
            }
            else {
                response.setStatus(Status.CLIENT_ERROR_FORBIDDEN);
                return STOP;
            }
        }

        return CONTINUE;
    }

}

Чтобы использовать SecureFilter, просто оберните сопоставления маршрута / ресурса:

    router.attach("/secure", new SecureFilter(getContext(), HelloSecureResource.class));
    router.attach("/secureWithRedirect", new SecureFilter(getContext(), HelloSecureResource.class, true));
...