登录无法使用CustomFormAuth和o:form正确转发 [英] Login not forwarding correctly with CustomFormAuth and o:form

查看:102
本文介绍了登录无法使用CustomFormAuth和o:form正确转发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的Web项目中实施Jakarta Security,为此,我遵循了令人惊叹的"Java EE 8中的JSF权威指南".由Bauke Scholtz和Arjan Tijms撰写,但似乎我正在碰壁.

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.

当我在地址栏中输入受限制的url时,转发会正确进行,我会看到登录页面,但是在提交表单后,该页面未重定向,并且登录页面似乎已重新加载(这些字段为空,但是地址栏中的url仍然是受限页面中的那个.)

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).

借助日志,我知道AuthenticationStatus返回为SUCCESS,但是即使那样,即使我手动将地址栏更改为另一个受限制的url,它也会转发到登录页面.

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.

如果我在地址栏中输入/login并提交身份验证,则重定向会正确进行.

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

如果我使useForwardToLogin = false正常工作,但getForwardURL总是返回null,并且我无法将用户重定向到他们想要访问的页面.

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.

感谢您的帮助.

ApplicationConfig.java

ApplicationConfig.java

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

}

login.xhtml

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

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,如您所见,我正在使用Omnifaces,Primefaces和Lombok.

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

推荐答案

按照Kukeltje的建议,我做了一个最小的工作示例,您可以在这里找到 https://github.com/Pilpin/mwe-jakartasecurity . 它是本书"Java EE 8中的JSF权威指南"一书的仓库安全部分的修改后的分支.由Bauke Scholtz和Arjan Tijms撰写=> https://github.com/Apress/definitive-guide-to-jsf- javaee8 .

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. 如此处所说用于精确的请求URI .
  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.

非常感谢库克尔特耶(Kukeltje)向正确的方向推动我.

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

这篇关于登录无法使用CustomFormAuth和o:form正确转发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆