User Authentication
This example shows how user authentication works and how to prevent unauthenticated users to access protected areas of your web-application:
Basically there are two components used for user authentication:
- [fleXive]'s JSF managed fxAuthenticationBean, a wrapper for basic authentication operations
- A filter which implements the javax.servlet.Filter interface
Building the login form
<!-- Output JSF error or info messages here -->
<h:messages showDetail="true" errorClass="errorMessage" infoClass="infoMessage"/> <!-- (1) -->
...
<h:form>
<fx:fieldSet legend="Login"> <!-- (2) -->
<h:outputText value="Username"/><br/>
<h:inputText id="username" value="#{fxAuthenticationBean.username}"/><br/> <!-- (3) -->
<h:outputText value="Password"/><br/>
<h:inputSecret id="password" value="#{fxAuthenticationBean.password}"/><br/> <!-- (4) -->
<h:selectBooleanCheckbox id="takeover" value="#{fxAuthenticationBean.takeover}"/> <!-- (5) -->
<h:outputText value="Takeover"/><br/>
<h:commandButton action="#{fxAuthenticationBean.login}">Login</h:commandLink> <!-- (6) -->
</fx:fieldSet>
</h:form>
(1) <h:messages/> on top renders JSF error or info messages - in this case it will render the error message on login failure.
(2) <fx:fieldSet/> tag renders a fieldset surrounding the form elements.
(3,4,5) The fxAuthenticationBean provides means for authenticating a user. A login form can be easily implemented by mapping its input fields to the appropriate bean properties i.e. username (3), password (4) and takeover (5).
Take over is used for user accounts where concurrent logins are disabled. If take over is checked and other users are logged in using the same credentials they will be logged out. If it is unchecked and another user is already logged in, logging in will fail.
(6) The action of the form's command button to the login() method of the fxAuthenticationBean performs the login.
public String login() {
try {
FxRequest request = FxJsfUtils.getRequest();
request.login(username, password, takeover);
request.getUserTicket();
return "loginSuccess";
} catch (Exception exc) {
new FxFacesMsgErr(exc).addToContext();
}
return null;
}
Restricting page access
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws ServletException, IOException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
final String contextPath = request.getContextPath();
CacheAdmin.getEnvironment();
if (FxContext.get().getTicket().isGuest() && request.getRequestURI().startsWith(contextPath + "/protected.area/")) { response.sendRedirect(contextPath + "/login.xhtml"); } else {
chain.doFilter(servletRequest, servletResponse);
}
}
To ensure only authenticated users access the protected area of the application, an authentication check has to be performed on every request. This is the security filter's job. It checks if a user has been authenticated (1), otherwise it sends him back to the login form (2).