PrimeFaces Mobile 5.2 和基于表单的 JAAS 登录不能一起工作

PrimeFaces Mobile 5.2 and form-based JAAS login not working together

我有一个 JSF 2.2 应用程序,其中包含 PrimeFaces 5.2 和基于表单的登录以及使用 Wildfly 8.2 和 PostgreSQL 的 JBoss 安全领域。

一切正常,完全符合预期。现在的问题是将上述设置与 PrimeFaces Mobile 一起使用。输入用户名和密码并单击登录按钮后,没有任何反应,因为我再次被重定向到登录视图,而不是重定向到原始请求页面或错误页面。

让我们从我的移动登录表单开始:

<ui:define name="content">
    <pm:content styleClass="content">
        <h:form id="loginForm" method="POST" prependId="false"
                onsubmit="document.getElementById('loginForm').action = 'j_security_check';">
                <p:focus for="j_username"/>
            <pm:field>
            <p:outputLabel value="Benutzername"></p:outputLabel>
           <h:inputText id="j_username" name="j_username" required="true" />
        </pm:field>
        <pm:field>
            <p:outputLabel value="Passwort"></p:outputLabel>
            <p:password id="j_password" name="j_password" redisplay="false" required="true" />
        </pm:field>
        <pm:field>
            <p:commandButton id="login" value="Login" ajax="false" />
        </pm:field>
        </h:form>
    </pm:content>
</ui:define>

如前所述,表单定义适用于非移动版本,对于移动版本,我只是添加了标签 pm_contentpm:field.

在检查 Chrome 中生成的 DOM 时,我可以看到呈现的移动版页面的表单和输入元素的 ID 与非移动版和 onsubmit 缺失:

<form id="j_idt6:loginForm" name="j_idt6:loginForm" method="post" action="/MyApp/login.xhtml" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="j_idt6:loginForm" value="j_idt6:loginForm">
<span id="j_idt6:j_idt32"></span><script type="text/javascript">$(function(){PrimeFaces.focus('j_idt6:username');});</script><div class="ui-field-contain"><label id="j_idt6:j_idt16" class="ui-outputlabel ui-widget">Benutzername</label><div class="ui-input-text ui-body-inherit ui-corner-all ui-shadow-inset"><input id="j_idt6:username" type="text" name="j_idt6:username"></div></div><div class="ui-field-contain"><label id="j_idt6:j_idt18" class="ui-outputlabel ui-widget">Passwort</label><div id="j_idt6:password" class="ui-input-text ui-body-inherit ui-corner-all ui-shadow-inset ui-input-has-clear"><input data-role="none" id="j_idt6:password" name="j_idt6:password" type="password"><a href="#" class="ui-input-clear ui-btn ui-icon-delete ui-btn-icon-notext ui-corner-all ui-input-clear-hidden"></a></div></div><div class="ui-field-contain"><button id="j_idt6:login" name="j_idt6:login" class="ui-btn ui-shadow ui-corner-all" onclick="" type="submit">Login</button></div><input type="hidden" name="javax.faces.ViewState" id="j_id1:javax.faces.ViewState:0" value="-5673897088131963149:-3654042330506594383" autocomplete="off">
</form>

现在非移动登录生成的输出:

<form id="loginForm" name="loginForm" method="post" action="/MyApp/login.xhtml" enctype="application/x-www-form-urlencoded" onsubmit="document.getElementById('loginForm').action = 'j_security_check';">
<input type="hidden" name="loginForm" value="loginForm">
<span id="j_idt11"></span><script type="text/javascript">$(function(){PrimeFaces.focus('j_username');});</script><input id="j_username" type="text" name="j_username"><input id="j_password" type="password" name="j_password" value=""><input id="login" type="submit" name="login" value="Login"><input type="hidden" name="javax.faces.ViewState" id="j_id1:javax.faces.ViewState:0" value="5464337132357101375:3961658655950415709" autocomplete="off">
</form>

如果我做对了,在移动版本中添加 id 似乎有问题。

如何解决此问题并在 PrimeFaces Mobile 5.2 中实现 POST 到 j_security_check

我能够根据@BalusC 的提示修改一个可行的解决方案,这样我的表单现在看起来像这样:

<ui:define name="content">
        <pm:content styleClass="content">
            <h:form>
                <pm:field>
                    <h:outputLabel for="username" value="Username" />
                    <h:inputText id="username" value="#{authenticationBean.username}"
                                 required="true" />
                    <h:message for="username" />
                </pm:field>
                <pm:field>
                    <h:outputLabel for="password" value="Password" />
                    <h:inputSecret id="password" value="#{authenticationBean.password}"
                                   required="true" />
                    <h:message for="password" />
                </pm:field>
                <pm:field>
                    <h:commandButton value="Login" action="#{authenticationBean.login()}" />
                </pm:field>
            </h:form>
        </pm:content>
</ui:define>

登录现在在登录方法中的 @ViewScoped 托管 bean AuthenticationBean 中以编程方式进行:

public void login() {
        log.info("Login attempt");

        FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext externalContext = context.getExternalContext();
        HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();

        try {
            request.login(username, password);
            log.info("Login successful");
            externalContext.redirect(originalURL);
        } catch (ServletException e) {
            // Handle unknown username/password in request.login().
            context.addMessage(null, new FacesMessage("Unknown login"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }