Search code examples
ajaxjsfjakarta-eeshiro

Apache-Shiro: User authenticates within AJAX, how to restore GET-Variables after login?


in my JavaEE-Application, I am using Apache Shiro[1] for user-authentication. My users are navigating via GET-URLs, as for example "/company/index.xhtml?companyId=327".

I have enabled programmatic login, following a guide[2] from BalusC:

SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(Faces.getRequest());

My problem is, that savedRequest.getRequestUrl() does not contain the previous mentioned GET-parameteres, when my case is asynchronous POST with or without RememberMe; just "/company/index.xhtml" is returned, for example. It seems as if "FacesAjaxAwareUserFilter" (see [2]) is not GET-params aware. Everything works fine on synchronous GET-calls.

How do I get the GET-parameters after an shiro-redirect because of authentication-needed in case of using "FacesAjaxAwareUserFilter"?

[1] https://shiro.apache.org/

[2] Followed this great article about JavaEE and Shiro: http://balusc.blogspot.de/2013/01/apache-shiro-is-it-ready-for-java-ee-6.html


Solution

  • JSF ajax requests are sent to the URL as generated by <h:form>. This is however by default not exactly the current URL including the query string, it's by default the current URI without the query string.

    There are several ways to fix this. The simplest but ugliest way is to use JS:

    <h:form id="foo">
        ...
    </h:form>
    <script>document.getElementById("foo").action += "?" + location.search;</script>
    

    The cleanest way would be to create a custom ViewHandler whose getActionURL() (as used by <h:form>) will return the desired URL with the query string.

    JSF utility library OmniFaces has already such a component which does that based on view parameters: the <o:form> which basically extends the <h:form> with support for includeViewParams="true" (exactly the same way as <h:link> does).

    <f:metadata>
        <f:viewParam name="companyId" value="#{bean.company}" />
    </f:metadata>
    ...
    <o:form includeViewParams="true">
        ...
    </o:form>