4

I have my application on a test server being executed exclusively over https. When I navigate without redirecting, it works perfectly:

Example:

<p:menuitem value="#{msg.customerScreen}" url="/restrict/customer.xhtml" />
<p:menuitem value="#{msg.productScreen}" url="/restrict/product.xhtml" />

But when I need to redirect to another page, it is redirecting to http instead of https. When using over http, it works perfectly:

<p:commandLink ajax="false" action="/commerce/store.xhtml?faces-redirect=true">
    <h:graphicImage library="images/BTN" name="btn_to_shop.gif"/>
</p:commandLink>

As a workaround I tryed to reconstruct the URL:

<p:commandLink ajax="false" action="#{authorizerBean.getCompleteURL('/commerce/store.xhtml?faces-redirect=true')}">
    <h:graphicImage library="images/BTN" name="btn_to_shop.gif"/>
</p:commandLink>

public String getCompleteURL(String page) {
    try {
        FacesContext ctxt = FacesContext.getCurrentInstance();
        ExternalContext ext = ctxt.getExternalContext();

        URI uri = new URI(ext.getRequestScheme(), null, ext.getRequestServerName(), ext.getRequestServerPort(), ext.getRequestContextPath(), null, null);
        return uri.toASCIIString() + page;
    } catch (URISyntaxException e) {
        throw new FacesException(e);
    }
}

The method getCompleteURL is being called and returning the URL correclty, but JSF is not redirecting to the new URL.

JBoss is receiving an HTTP connection. Who manages the HTTPS is Apache, that redirects to JBoss:

<VirtualHost *:443>

    ...

    ProxyPass / http://server:8080/
    ProxyPassReverse / http://server:8080/
</VirtualHost>

I would prefer to solve this issue without using the getCompleteURL, but if it is not possible, please help me with other approaches.

DHansen
  • 225
  • 3
  • 13
  • possible duplicate of [Issues with JSF navigation rules using redirect on HTTPS](http://stackoverflow.com/questions/15636609/issues-with-jsf-navigation-rules-using-redirect-on-https) – kolossus Aug 01 '15 at 21:02

2 Answers2

5

I found a solution for this issue. I think it is happening because Apache receives the https connection and forwards for JBoss via http. Then when I redirect to another page, JSF doesn't know that it should be made via https.

With a ConfigurableNavigationHandler I can intercept when it is redirected and mount the correct URL.

public class NavigationHandler extends ConfigurableNavigationHandler {

    private ConfigurableNavigationHandler concreteHandler;

    public NavigationHandler(ConfigurableNavigationHandler concreteHandler) {
        this.concreteHandler = concreteHandler;
    }

    @Override
    public void handleNavigation(FacesContext context, String fromAction, String outcome) {
        if (outcome != null && outcome.contains("faces-redirect=true")) {
            try {
                outcome = "https://server.com/project" + outcome;
                context.getExternalContext().redirect( outcome );
            } catch (IOException e) {
                throw new FacesException(e);
            }
        } else {
            concreteHandler.handleNavigation(context, fromAction, outcome);   
        }
    }
}

in faces-config.xml:

<application>
    <navigation-handler>com.example.NavigationHandler</navigation-handler>
</application> 
DHansen
  • 225
  • 3
  • 13
0

Another solution is to set

RequestHeader set X-Forwarded-Proto https
RequestHeader set X-Forwarded-Port 443

on the VirtualHost in Apache.

JSF will then know that the redirect should be to a HTTPS connection and no code changes are required.

I have used this with Apache and Wildfly.

Bjørn Stenfeldt
  • 1,432
  • 1
  • 18
  • 25