Login not forwarding correctly with CustomFormAuth and o:form

99封情书 提交于 2020-07-15 09:22:10

问题


I'm trying to implement Jakarta Security on my web project, to do so I'm following the amazing "The Definitive Guide to JSF in Java EE 8" by Bauke Scholtz and Arjan Tijms but it seems that I'm hitting a wall.

When I type in a restricted url in the address bar the forward happens properly and I see the login page but after submitting the form the page is not redirected and the login page seems to be reloaded (the fields are emptied, but the url in the address bar is still the one from the restricted page).

With the help of the logs I know that the AuthenticationStatus returns as SUCCESS but even then if I manually change the address bar to another restricted url it gets forwarded to the login page.

If I type /login in the address bar and submit the authentication and redirect happens properly.

It seems that if I make useForwardToLogin = false it works properly but then getForwardURL always returns null and I can not redirect the user to the page they wanted to get to.

Thanks for your help.

ApplicationConfig.java

@CustomFormAuthenticationMechanismDefinition(
        loginToContinue = @LoginToContinue(
                loginPage = "/login",
                errorPage = ""
        )
)
@FacesConfig
@ApplicationScoped
public class ApplicationConfig {

}

login.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:c="http://java.sun.com/jsp/jstl/core"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions"
                xmlns:p="http://primefaces.org/ui"
                xmlns:o="http://omnifaces.org/ui"
                template="/WEB-INF/templates/login.xhtml">
    <ui:define name="content">
        <c:choose>
            <c:when test="#{not empty request.userPrincipal}">
                <div>Already logged</div>
            </c:when>
            <c:otherwise>
                <o:form>
                    <p:inputText id="login" value="#{loginBacking.userName}" required="true"/>
                    <p:password id="pwd" value="#{loginBacking.password}" required="true"/>
                    <p:inputNumber id="otp" value="#{loginBacking.otp}" />
                    
                    <o:messages id="messages" var="message">
                        <div class="#{fn:toLowerCase(message.severity)}">#{message.summary}</div>
                    </o:messages>

                    <p:commandButton value="Submit" action="#{loginBacking.login}" update="@form"/>
                </o:form>
            </c:otherwise>
        </c:choose>
    </ui:define>
</ui:composition>

LoginBacking.java

@Named
@RequestScoped
public class LoginBacking {
    @Inject private SecurityContext securityContext;

    @Getter @Setter private String userName;
    @Getter @Setter private String password;
    @Getter @Setter private Integer otp;

    public void login() {
        switch (continueAuthentication()) {
            case SEND_CONTINUE:
                Faces.responseComplete();
                break;
            case SEND_FAILURE:
                Messages.addGlobalFatal("Login failed.");
                break;
            case SUCCESS:
                redirect();
                break;
        }
    }

    private AuthenticationStatus continueAuthentication() {
        return this.securityContext.authenticate(
                Faces.getRequest(),
                Faces.getResponse(),
                AuthenticationParameters.withParams()
                        .newAuthentication(getForwardURL() == null)
                        .credential(new CustomCredential(userName, password, otp))
        );
    }

    private void redirect() {
        CustomUser user = securityContext.getPrincipalsByType(CustomPrincipal.class).stream()
                .map(CustomPrincipal::getCustomUser)
                .findAny()
                .orElse(null);

        if (user == null) Messages.addGlobalFatal("Something went wrong.");

        String forwardURL = getForwardURL();
        if (forwardURL != null) {
            Faces.redirect(forwardURL);
            return;
        }
        
        Faces.redirect(Faces.getRequestContextPath() + "/restricted/index");
    }

    public void logout() throws ServletException {
        Faces.logout();
        Faces.invalidateSession();
        Faces.redirect("login");
    }

    public String getForwardURL() {
        String requestURI = Faces.getRequestAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
        String queryString = Faces.getRequestAttribute(RequestDispatcher.FORWARD_QUERY_STRING);

        if (requestURI == null) return null;
        return (queryString == null) ? requestURI : (requestURI + "?" + queryString);
    }
}

FIY, as you can see, I'm using Omnifaces, Primefaces and Lombok.


回答1:


Following Kukeltje advice I made a minimal working example that you can find here https://github.com/Pilpin/mwe-jakartasecurity. It is a modified fork of the security part of the repo for the book "The Definitive Guide to JSF in Java EE 8" by Bauke Scholtz and Arjan Tijms => https://github.com/Apress/definitive-guide-to-jsf-javaee8.

It's working perfectly fine so I decided to add omnifaces and primefaces to it and realized :

  1. As said here How can I redirect to the original request url with Java EE Security @CustomFormAuthenticationMechanismDefinition if you're using primefaces' p:commandButton you should add the ajax=false property to it.
  2. If you're using omnifaces' o:form you should add the useRequestURI="false" property to it. It makes sense because my fork uses forward to get to the login page so the URL and URI are the ones of whatever page you wanted to get to and when useRequestURI is set to true (default) on o:form it submits the form to the exact request URI so not to the login page.

Thanks a lot to Kukeltje for nudging me in the right direction.



来源:https://stackoverflow.com/questions/62523627/login-not-forwarding-correctly-with-customformauth-and-oform

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!