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

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

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

Related

<h:commandButton> not working inside <ui:define>

I created a facelet template called loginRegisterTemplate.xhtml. When I use it in a template client and I place a in it, the method in the managed bean is not invoked. Without the template the button is working fine. Why is this happening?
<ui:composition template="resources/css/faceletsTemplates/loginRegisterTemplate.xhtml">
<ui:define name="top">
Login Page
</ui:define>
<ui:define name="content">
<div align="center">
<h:panelGrid columns="3" columnClasses="rightalign,leftalign,leftalign">
<h:outputLabel value="Username:" for="userName"/>
<h:inputText id="userName" label="Username" required="true" value="#{loginBean.userName}" />
<h:message for="userName" />
<h:outputLabel value="Password:" for="password"/>
<h:inputText id="password" label="Password" required="true" value="#{loginBean.password}" />
<h:message for="password" />
</h:panelGrid><br/>
<h:button value="Back to Home" outcome="home"/>
<h:commandButton id="login" value="Login" action="#{loginBean.doLogin}"/>
</div>
</ui:define>
</ui:composition>
</h:body>
The simple <h:button> next to it, on the other side, is working fine.
Here is the body of my template file:
<h:body>
<div id="top">
<ui:insert name="top">Top</ui:insert>
</div>
<div id="content" class="center_content">
<ui:insert name="content">Content</ui:insert>
</div>
</h:body>
I have looked here: h:commandLink / h:commandButton is not being invoked but I couldn't find which problem causes that.
Thanks!
Why is the h:commandButton not working?
Your problem is number 1 in the answer you have checked.
UICommand and UIInput components must be placed inside an UIForm
component, e.g. <h:form>.
Why is the h:button working then ?
from the h:button docs:
Render an HTML "input" element of type "button". The value of the
component is rendered as the button text and the outcome of the
component is used to determine the target URL which is activated by
onclick.
So ...
JSF will put your h:button outcome value in a javascript function that will be executed at an onclick event. But it will execute the action of the h:commandButton on the form submit with the POST method, so there should be a form to submit.

get j_username in j_security_check JSF 2.0

I have simple page, I want to retrieve j_username to save it in session as a logged in user, i can't fetch it from the form. here Server it self perform authentication in this code
<h:form id="login" onsubmit="document.getElementById('login').action='j_security_check';" prependId="false">
<h:panelGrid columns="2">
<p:outputLabel for="j_username" value="Username" />
<p:inputText id="j_username" name="j_username"/>
<p:outputLabel for="j_password" value="Password" />
<p:password id="j_password" name="j_password" value=""/>
<p:commandButton style="font-size:15px" type="submit" value="Login" ajax="false"/>
<p:commandButton style="font-size:15px" type="clear" value="Clear" ajax="false"/>
</h:panelGrid>
</h:form>
It's available by HttpServletRequest#getRemoteUser() which is in JSF context delegated by ExternalContext#getRemoteUser().
So, this should do either in the view:
<ui:fragment rendered="#{empty request.remoteUser}">
<p>This is only rendered when someone's NOT logged in.</p>
</ui:fragment>
<ui:fragment rendered="#{not empty request.remoteUser}">
<p>This is only rendered when someone's been logged in.</p>
<p>Welcome, you're logged in as #{request.remoteUser}!</p>
</ui:fragment>
or in the managed bean:
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
String username = ec.getRemoteUser();
// ...
Unrelated to the concrete problem: it's better to get rid of that onsubmit nonsense and just use plain <form> instead of <h:form>.
<form id="login" action="j_security_check">
This way it'll also work on JS-disabled clients.
See also:
Performing user authentication in Java EE / JSF using j_security_check

Omnifaces ValidateEqual Does not perform validation

I am trying out the Omnifaces validators especially the validateEqual and so I created a test page such as this.
<p:messages autoUpdate="true" showDetail="false" />
<h:form id="registerForm" prependId="false">
<p:panelGrid columns="2" styleClass="register-grid">
<h:outputLabel for="password" value="Password *" />
<p:inputText id="password" value="" label="Password"
requiredMessage="Password is required" size="30">
<f:validateRequired />
</p:inputText>
<h:outputLabel for="confirmPassword" value="Confirm Password *"
requiredMessage="Confirm Password is required" />
<p:inputText id="confirmPassword" value="" label="Confirm Password" requiredMessage="Confirm password is required"
size="30">
<f:validateRequired />
</p:inputText>
<o:validateEqual components="password confirmPassword" message="Passwords are not equal"/>
<f:facet name="footer">
<p:commandButton value="Register" action="/pages/public/login"/>
<p:commandButton value="Cancel" immediate="true" action="/pages/public/login"/>
</f:facet>
</p:panelGrid>
</h:form>
Not sure but nothing is happening and I see from firebug below error.
<partial-response>
<error>
<error-name>class javax.faces.component.UpdateModelException</error-name>
<error-message>/pages/public/register.xhtml #26,57 value="": Illegal Syntax for Set Operation</error-message>
</error>
<changes>
<extension ln="primefaces" type="args">{"validationFailed":true}</extension>
</changes>
</partial-response>
What could be the cause?
/pages/public/register.xhtml #26,57 value="": Illegal Syntax for Set Operation
This is basically telling that it's not possible to perform a "set" operation (a setter method call) on an empty value expression.
Either remove the value attribute altogether (at least from the "confirm" field), or specify a valid value expression such as value="#{bean.password}" (at least for the first field). So, basically:
<p:inputText id="password" value="#{bean.password}" label="Password"
requiredMessage="Password is required" size="30" required="true" />
<p:inputText id="confirmPassword" label="Confirm Password"
requiredMessage="Confirm password is required" size="30" required="true" />
<o:validateEqual components="password confirmPassword"
message="Passwords are not equal" />
This has nothing to do with using <o:validateEqual>. You'd have exactly the same problem when not using it. You may however want to use OmniFaces FullAjaxExceptionHandler in order to get a real error page on an exception during an ajax request instead of complete lack of visual feedback.

table not showing data when uses pagintion

I have a from like this
<h:form id="logForm" prependId="false">
<div class="leftcol">
....
<h:commandButton value="Apply Filters"
action="#{exporterReview.applyFilterAction}">
</h:commandButton><br></br><br></br>
....
</div>
<div class="rightcol1" >
<p:dataTable var="exporter"
value="#{exporterReview.exporters}"
paginator="true" rows="5"
height="400" paginatorPosition="top"
emptyMessage="#{exporterReview.noExporterFound}">
<p:column>
<div style="....">
<h:graphicImage value="#{exporter.imgPath}" />
</div>
<div style="...">
<h:commandButton value="Update"
action="#{exporterReview.updateExporter}"
rendered="#{login.updateState}"
style="... ">
<f:param name="exporterid"
value="#{exporter.exporterId}" />
</h:commandButton>
</div>
<div class="arrowbuttons">
<span class="arrow"></span>
</div>
<p:spacer height="10" width="20"/>
<h:commandButton value="#{exporter.organizationName}"
action="#{exporterReview.viewExporter}"
style="...">
<f:param name="exporterid" value="#{exporter.exporterId}" />
<f:param name="disableLink" value="#{exporter.disableLink}" />
</h:commandButton>
<div style='padding-top:10px'>
<h:outputLabel value="City: " style="color: #1c6ace;"/>
<h:panelGroup rendered="#{not exporter.disableLink}">
<h:commandLink value="#{exporter.cityName}"
style="text-decoration: underline"
disabled="#{exporter.disableLink}"
onclick="openCityPopup(#{exporter.cityId});" >
</h:commandLink>
</h:panelGroup>
<h:panelGroup rendered="#{exporter.disableLink}">
<h:outputText value="#{exporter.cityName}"></h:outputText>
</h:panelGroup>
</div>
<div style='padding-top:3px'>
<h:outputLabel value="Email Address: " style="color: #1c6ace;"/>
<a href="mailto:#{exporter.emailAddress}">
<h:outputText value="#{exporter.emailAddress}"
style="..">
</h:outputText>
</a>
</div>
<div style='padding-top:3px'>
<h:outputText value="#{exporter.categoryDesc}"
escape="false" />
</div>
<div class="horizontalline"></div>
</p:column>
</p:dataTable>
</div>
</h:form>
Here is the filter method
public void applyFilterAction() {
....
//Setting whereParam so that whenever user navigate from page And return back
// the grid is populated with the previous search criteria
session.setAttribute("settingWhereParam", whereParam);
getExporterGrid();
} //end of applyFilterAction
private void getExporterGrid() {
....
exporters.add(new Exporter(Datatable values));
} //end of getExporterGrid
The problem is when i am on first page and do the search then every thing works fine. Here is the first picture.
Then if i apply search then it becomes
But if i do pagination , say go to page 4 and then apply the search then no result shows
But then nothing show
Why it is happening? What i am doing wrong ? I am using Prime faces 2.2. Its an old program.
Thank you
I'm not sure if this will work in primefaces 2.2, but in version 3+, you can specify an update attribute.
Your commandButton would look like this:
<h:commandButton value="Apply Filters" action="#{exporterReview.applyFilterAction}" update="#form">
I did it :). Actually i did a workaround. What i did, i used onClick event on my filter Button. Like
<h:commandButton id="filterButton"
value="Apply Filters"
style=""
action="#{exporterReview.applyFilterAction}"
onclick="filterButtonClick(event)" />
Now when button is clicked, then first my client side code will run. So i get all the values and then using ajax call the servlet, and save the result in session object. After that my server side code will run, and my action method invoked, in which i simple return the url of the same page.
public String applyFilterAction() {
return "Exporter_Review?faces-redirect=true";
} //end of applyFilterAction()
Now when page invoke i simply check for the result in the session. And if session object present then simply get the values from that object and shows the result. And when i leave the page i simply put null in the session against object, now default is used. Now everything is working fine :)

Struts2: Hidden field and anchor tag <s:a> values In Action Class

I am working on a struts2 application. In my jsp page I have 2-3 anchor tag and 2-3 hidden fields like
<s:a href="#">File 1</s:a>
<s:a href="#">File 2</s:a>
<s:a href="#">File 3</s:a>
and
<s:hidden name=" hidden1" />
<s:hidden name=" hidden2" />
<s:hidden name=" hidden3" />
Now please let me know, In my action class how can I get value of all the hidden fields and anchor tag which was clicked.
I had tried following
<s:a href="#" action=”someAction”>File 1</s:a>
Its working but didn’t transfer value of hidden fileds.
Also
<s:a href="#" name=”File1” onclick=”submit”>File 1</s:a>
But no gain.
Looking for your reply.
Like Boris said, you need to put the hidden fields inside a form, and submit that form, OR you can add them as URL parameters to your links. The best method is probably using a form with POST so the hidden fields aren't on your browser's location bar.
Here's an example
<s:form id="myform" name="myform" action="someAction" method="POST">
<s:hidden name=" hidden1" value="first value"/>
<s:hidden name=" hidden2" value="second value"/>
<s:hidden name=" hidden3" value="third value"/>
Submit with link
<s:submit value="%{'Submit with button'}" />
</s:form>
Since this really has nothing to do with struts2, here's an example with pure HTML:
<form id="myform" name="myform" action="someAction.action" method="POST">
<input type="hidden" name=" hidden1" value="first value"/>
<input type="hidden" name=" hidden2" value="second value"/>
<input type="hidden" name=" hidden3" value="third value"/>
Submit with a link
<br/>
<input type="submit" value="Submit with a button"/>
</form>

Resources