I created a simple JSF login page, and I'm trying to integrate it with spring security.
Here is the form element from login.xhtml
<h:form>
<h:outputLabel value="User Id:" for="userId"/>
<h:inputText id="j_username" label="User Id"
required="true" value="#{loginBean.name}" >
</h:inputText>
<h:outputLabel value="Password: " for ="password"/>
<h:inputSecret id="j_password" value="#{loginBean.password}" />
<h:commandButton value="Submit" action="#{j_spring_security_check}" />
</h:form>
But the rendered html page has something like the below. Take a look at the form action and the input tag's names
The form element
<form id="j_idt6" name="j_idt6" method="post"
action="/jsfproject2/faces/login.xhtml"
enctype="application/x-www-form-urlencoded">
And the input tags
User Id:</label><input id="j_idt6:j_username" type="text"
name="j_idt6:j_username" />
Now I want form action to be /j_spring_security_check
and input boxes to be 'j_username' and j_password
How can we achieve this ?
There are two options for Spring Security to work.
prependId="false"
on a JSF formAs <h:form>
is a naming container, it prepends id of its children with the specified id
, or the autogenerated id, so as Spring Security expects ids to remain unchainged, just don't prepend the ids:
<h:form prependId="false">
<h:outputLabel value="User Id: " for="userId" />
<h:inputText id="j_username" label="User Id" required="true" value="#{loginBean.name}" />
<h:outputLabel value="Password: " for ="password" />
<h:inputSecret id="j_password" value="#{loginBean.password}" />
<h:commandButton value="Submit" action="#{loginBean.login}" />
</h:form>
Note that #{j_spring_security_check}
is a wrong action method: it needs to be #{loginBean.login}
with the following contents:
public String login() {
//do any job with the associated values that you've got from the user, like persisting attempted login, etc.
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext extenalContext = facesContext.getExternalContext();
RequestDispatcher dispatcher = ((ServletRequest)extenalContext.getRequest()).getRequestDispatcher("/j_spring_security_check");
dispatcher.forward((ServletRequest)extenalContext.getRequest(), (ServletResponse)extenalContext.getResponse());
facesContext.responseComplete();
return null;
}
Basically, all you need to do is dispatch to /j_spring_security_check
and have j_username
and j_password
as request parameters.
Basically, there's no particular need to mess with JSF form on this issue, in case you don't need to do some extra things apart from authentication, and plain HTML form is sufficient for Spring Security to do its job.
<form action="/j_spring_security_check" method="POST">
<label for="j_username">User Id: </label>
<input id="j_username" name="j_username" type="text" />
<label for="j_password">Password: </label>
<input id="j_password" name="j_password" type="password"/>
<input type="submit" value="Submit"/>
</form>
Thats how i did it:
<form action="${request.contextPath}/appLogin" method="POST">
<h:form prependId="false">
<p:inputText id="app_username" placeholder="Username" name="app_username" styleClass="Wid80 TexAlCenter Fs18" required="true"/>
<p:password id="app_password" placeholder="Password" name="app_password" label="Password" required="true" styleClass="Wid80 TexAlCenter Fs18"/>
<button type="submit" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only Wid60">
<span class="ui-button-text">Login</span>
</button>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</h:form>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
I'm using the Premium Theme Ronin from Primefaces and custom login URLs like "appLogin" and custom Parameters like "app_username".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With