如何在ELB后面的tomcat上重定向到https

时间:2014-12-18 08:51:49

标签: tomcat ssl amazon-web-services nginx amazon-elb

我在AWS上进行了以下设置

ELB(终止SSL) - > nginx在80上接收http并转发到 - > tomcat on 8080

但是当我在我的servlet中执行response.sendRedirect(" / somepath")时,浏览器会将其接收为302 http://example.com/somepath

但我希望浏览器获得https://example.com/somepath,如何在tomcat或nginx中实现此功能而不在其上设置SSL。

2 个答案:

答案 0 :(得分:4)

这是因为response.sendRedirect();

  

SSL卸载服务器实际上会导致https网址出现此问题   在sendRedirect的情况下转换为http URL。让我们试试吧   了解这一切是如何发生的。当https URL到达时   中间SSL卸载服务器,请求被解码(卸载   解码任务本来是由实际目标完成的   服务器否则)进入http请求,SSL卸载器现在发送   将http请求解码到实际的目标服务器(它可能会去   通过其他几个中介服务器用于其他目的)。   现在,目标服务器不知道它最初是否为https   请求与否,它仅将其视为http请求。这是   为什么servlet在目标服务器上调用sendRedirect的原因   结果到重定向资源的http URL(有一个亲戚   URL)和相同的http URL被发送回客户端浏览器。   请记住,此URL不会出现SSL卸载服务器   因为它是一个http请求而不是一个https请求。如果重定向   resource是一个绝对的https URL,也是一个中间SSL   Offloader之前可以将该https请求转换为http请求   它到达客户端浏览器。

该问题的解决方案是在HttpServletResponseWrapper中实现Filter并覆盖sendRedirect。

过滤

public class AbsoluteSendRedirectFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException { }
    public void destroy() { }
    public void doFilter(ServletRequest request,
            ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        //continue the request
        chain.doFilter(request, new SendRedirectOverloadedResponse(request, response));
    }
}

HttpServletResponseWrapper

public class SendRedirectOverloadedResponse extends HttpServletResponseWrapper {

    private HttpServletRequest m_request;
    private String prefix = null;

    public SendRedirectOverloadedResponse(HttpServletRequest inRequest,
            HttpServletResponse response) {
        super(response);
        m_request = inRequest;
        prefix = getPrefix(inRequest);
    }

    public void sendRedirect(String location) throws IOException {
        String finalurl = null;
        if (isUrlAbsolute(location)) {
            finalurl = location;
        } else {
            finalurl = fixForScheme(prefix + location);
        }
        super.sendRedirect(finalurl);
    }

    public boolean isUrlAbsolute(String url) {
        return url.toLowerCase().startsWith("http");
    }

    public String fixForScheme(String url) {
        //alter the url here if you were to change the scheme return url;
    }

    public String getPrefix(HttpServletRequest request) {
        StringBuffer str = request.getRequestURL();
        String url = str.toString();
        String uri = request.getRequestURI();
        int offset = url.indexOf(uri);
        String prefix = url.substring(0,offset);
    }
}

资源来自这里:
http://www.hoitikwong.com/2013/03/the-mystery-case-of-https-becoming-http.html
http://geekexplains.blogspot.in/2008/06/https-becoming-http-in-case-of.html

答案 1 :(得分:0)

尝试为LB级别的所有请求设置IS_SSL = ssl请求标头。然后,nginx使用https传递与原始URL一样的响应