per*_*ssf 2 jsf login j-security-check primefaces
我已经开发了一个简单的登录表单,可以在我的JSF + PrimeFaces页面中使用:
<form action="j_security_check" method="post">
<p:dialog modal="true" header="Login" widgetVar="loginDlg">
<h:panelGrid columns="3" cellpadding="5">
<h:outputLabel for="j_username">Username:</h:outputLabel>
<h:inputText id="j_username" required="true" />
<h:message for="j_username" />
<h:outputLabel for="j_password">Password:</h:outputLabel>
<h:inputSecret id="j_password" required="true" />
<h:message for="j_password" />
<br />
<h:commandButton value="Login" />
</h:panelGrid>
</p:dialog>
</form>
Run Code Online (Sandbox Code Playgroud)
尝试使用空密码,但缺少的密码(必需)不会被h:message组件捕获.我也转而p:commandButton认为问题可能出在按钮的Ajax行为中,但页面没有呈现,因为PrimeFaces抱怨CommandButton不在表单元素中.容器抛出的异常是:
com.sun.enterprise.security.auth.login.common.LoginException: Login failed: Access denied on empty password for user pippo
Run Code Online (Sandbox Code Playgroud)
总结一下,我有两个问题:
该j_security_check请求由Web容器来处理,而不是由JSF.这说明 required="true"不行.只有在与命令按钮关联的操作方法中使用JSF <h:form>和编程登录时,它才有效HttpServletRequest#login().
最好你可以做的是一个confiure <form-error-page>在web.xml指向非常相同的URL <form-login-page>.然后,您可以检查请求是否已j_security_check自行转发,这意味着发生了登录错误.
<h:panelGroup rendered="#{requestScope['javax.servlet.forward.servlet_path'] == '/j_security_check'}">
<h:outputText value="Unknown login, please try again" styleClass="error" />
</h:panelGroup>
Run Code Online (Sandbox Code Playgroud)
用这个代替<h:message>.
至于为什么<p:commandButton>抱怨没有形式只是因为你没有使用<h:form>.
与具体问题无关,<form>(或者<h:form>当你决定切换到程序化登录时)可以更好地放在身体内<p:dialog>,而不是外面.在<p:dialog>通过JS可以搬迁到身体的结束,这将导致它不能是这样的形式了.