Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I do Spring Security authentication from within a JSF form

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 ?

like image 645
user2434 Avatar asked May 24 '13 08:05

user2434


2 Answers

There are two options for Spring Security to work.

Use prependId="false" on a JSF form

As <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.

Use plain HTML form

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>
like image 90
skuntsel Avatar answered Sep 21 '22 21:09

skuntsel


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".

like image 31
Marian Avatar answered Sep 25 '22 21:09

Marian