我有一个JSF登录页面(用于Spring Security)和一条全局消息,用于显示错误登录用户/通行证的消息。
这是我的表格:
<f:event listener="#{loginBean.updateMessages}" type="preRenderView"/>
<h:form prependId="false" >
<h:outputLabel value="User Name:" for="username"/>
<h:inputText id="username" required="true" value="#{loginBean.name}"/>
<h:message id="usernMsg" for="username"/> <br/>
<h:outputLabel value="Password:" for="password"/>
<h:inputSecret id="password" value="#{loginBean.password}" required="true"/>
<h:message id="passMsg" for="password"/><br/>
<h:messages id="glbMsg" globalOnly="true"/><br/>
<h:commandButton value="Submit" action="#{loginBean.doLogin}"/>
</h:form>
我用updateMessages()
:更新消息
public void updateMessages() {
Exception ex = (Exception) FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
.get(WebAttributes.AUTHENTICATION_EXCEPTION);
if (ex != null) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, ex.getMessage(), ""));
setUsername("");
setPassword("");
}
}
问题是,当用户输入错误的凭据时,会显示消息,但当用户刷新登录页面(使用F5
或在文本字段为空时单击提交按钮)时,上一个全局消息(glbMsg
)值不会删除。
我在提交按钮中尝试了ajax render="..."
,但没有成功。
现在以正确的方式再次回顾这个问题。实际上,您并不想清除h:messages
。您实际上想要清除异常(它触发了h:messages
)。它只是每次都重新显示,因为异常不是每次都是null
。
Spring Security将最后一次身份验证失败作为异常存储在会话中。你获得它的方式很明显:
Exception ex = (Exception) FacesContext.getCurrentInstance().getExternalContext()
.getSessionMap().get(WebAttributes.AUTHENTICATION_EXCEPTION);
除非您使会话无效,或者Spring Security自己将其全部删除,否则它将在整个会话中保持不变。由于Spring Security显然不会删除它,所以您必须自己删除它。
Exception ex = (Exception) FacesContext.getCurrentInstance().getExternalContext()
.getSessionMap().remove(WebAttributes.AUTHENTICATION_EXCEPTION);