You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by "Geoff Callender (JIRA)" <ji...@apache.org> on 2017/04/18 03:16:41 UTC

[jira] [Created] (TAP5-2577) HTTPS + Load balancer not working with InjectPage or Class

Geoff Callender created TAP5-2577:
-------------------------------------

             Summary: HTTPS + Load balancer not working with InjectPage or Class
                 Key: TAP5-2577
                 URL: https://issues.apache.org/jira/browse/TAP5-2577
             Project: Tapestry 5
          Issue Type: Bug
          Components: tapestry-core
    Affects Versions: 5.4.2, 5.4.1
            Reporter: Geoff Callender


I have a secured application, meaning it insists on HTTPS, so it should return HTTPS URLs for everything, but it doesn't. When an event handler returns a page class or an injected page, Tapestry returns an HTTP URL.

public class Page1 {

	@InjectPage
	private Page2 page2;

	Object onToPage2InjectPage() {
		return page2;
	}

	Object onToPage2Class() {
		return Page2.class;
	}

}

The problem started when I switched handling of HTTPS to a load balancer (AWS Application Load Balancer). It forwards the request as HTTP, along with the HTTPS headers intact. Normally Tapestry recognises the request is secure and returns a secure URL, but not in the 2 cases above.

I've narrowed the problem down to a method in RequestSecurityManagerImpl:  

    public LinkSecurity checkPageSecurity(String pageName)
    {
        if (!securityEnabled)
        {
            return request.isSecure() ? LinkSecurity.SECURE : LinkSecurity.INSECURE;
        }

        boolean securePage = isSecure(pageName);

        if (request.isSecure() == securePage)
        {
            return securePage ? LinkSecurity.SECURE : LinkSecurity.INSECURE;
        }

        // Return a value that will, ultimately, force an absolute URL.

        return securePage ? LinkSecurity.FORCE_SECURE : LinkSecurity.FORCE_INSECURE;
    }

It assumes that a secure page is HTTPS and therefore it returns LinkSecurity.SECURE instead of LinkSecurity.FORCE_SECURE . Consequently, Tapestry returns a relative URL instead of an absolute URL specifying "https://".  

I see 3 possible solutions:  

(1) Always return absolute URLs.  
(2) Instead of relative URLs, return a protocol-relative URL (i.e. "//" instead of "https://" or "http://").  
(3) Modify the code to handle the possibility that protocol and isSecure() disagree. For example (this code snippet has been tested and is running live):  

        if (request.isSecure() == securePage) 
        {
            if (request.isSecure() && request.getAttribute("servletAPI.scheme").equals("https")
	        || !request.isSecure() && request.getAttribute("servletAPI.scheme").equals("http")) 
            {
                    return securePage ? LinkSecurity.SECURE : LinkSecurity.INSECURE;
            }
            else 
            {
                return securePage ? LinkSecurity.FORCE_SECURE : LinkSecurity.FORCE_INSECURE;
            }
        }

Is possibility 1 a bad idea? Are longer URLs really a big deal?  

Some people suggest possibility 2 has downsides such as page URLs not standing on their own if copied and pasted. Maybe that's an issue.  

I used possibility 3 to solved my problem. It works.



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)