Spring Security is the security framework which is a part of Spring framework technology stack. It is a mature, powerful and flexible security solution for enterprise applications. Earlier, it was widely known as Acegi Security and now it is called Spring Security. Recently I have been working on a product of mine and I currently use JSF/Facelets and Spring Webflow /Spring Security and JPA technologies to build the product. Spring webflow out of the box integrates with Spring Security and provides access to implicit expression language ( EL) variable called currentUser to get access to the authenticated principal name. I wanted more than this in other pages that are not part of Spring webflow related.
Authentication Tag Libraries
Spring Security out of the box provides the following tag support to get the authenticated principal in JSP fragments.
<security:authentication property="principal.username"/>
However, Spring Security does not provide any support of using similar tags in JSF/Facelets view technology. I did some research and found the following weblog
My big thanks to Çağatay Çivici who showed us a way to use "acegijsf" tag in JSF/Facelets. However, the website need some more fine grained details as to how to wire everything together to make use of his library. So it is my humble attempt at explaining as to how to use his library in a less invasive way. I hope this will help any novice JSF/Facelets developer to make use of tag support in JSF/Facelets view technology.
Detailed Steps
- Download acegi-jsf-1.1.3.jar
- Place the above said jar in WEB-INF/lib of your JSF/Facelets web application.
- Please add the following xml fragments into your faces-config.xml located under WEB-INF of your web application.
Now, you have to add the following namespace to your facelet .XHTML
<component>
<component-type>net.sf.jsfcomp.acegijsf.Authorize</component-type>
<component-class>net.sf.jsfcomp.acegijsf.Authorize</component-class>
</component>
<component>
<component-type>net.sf.jsfcomp.acegijsf.Authentication</component-type>
<component-class>net.sf.jsfcomp.acegijsf.Authentication</component-class>
</component>
- e.g. xmlns:acegijsf="http://sourceforge.net/projects/jsf-comp/acegijsf"
- Thats it. Now you can utilize the following tags inside your XHTML.
<acegijsf:authorize ifAllGranted="ROLE_ADMIN">The attribute names are same both in jsp tag and the jsf component. You just give a role list seperated with a comma(Whitespaces omitted). All of these attributes can be bound to a value using EL.
Add the components that are only visible to the users that satisfy the requirements here.
</acegijsf:authorize>
ifAllGranted = User must be in all of the roles
ifAnyGranted = User must be in any of the roles
ifNotGranted = None of the roles must be granted for the user
22 comments:
Great Work. It works like charm.
I am still trying to figure out how to make the following scriplet work in JSF/Facelets xhtml file
Your principal object is....: = request.getUserPrincipal()
Any pointers/suggestions will be greatly appreciated
try <acegijsf:authentication operation="username"/>
The above said tag will display the autenticated username similar to java.security.Principal object containing the name of the current authenticated user.
It works great once you're authenticated but before I'm receiving a NPE when trying <security:authentication operation="username" />. Here's the trace:
java.lang.NullPointerException
at org.apache.myfaces.shared_impl.renderkit.html.HtmlResponseWriterImpl.write(HtmlResponseWriterImpl.java:574)
at net.sf.jsfcomp.acegijsf.Authentication.encodeBegin(Authentication.java:51)
at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:280)
at org.ajax4jsf.renderkit.RendererBase.renderChildren(RendererBase.java:262)
at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:284)
at org.ajax4jsf.renderkit.RendererBase.renderChildren(RendererBase.java:262)
at org.ajax4jsf.renderkit.html.AjaxOutputPanelRenderer.encodeChildren(AjaxOutputPanelRenderer.java:79)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:594)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:239)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:246)
at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:455)
at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:108)
at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:189)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:41)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:140)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:152)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1081)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1016)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:145)
at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:154)
at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:260)
at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:366)
at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:493)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:190)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:130)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:87)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:771)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:679)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:546)
at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:478)
at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.forward(WebAppRequestDispatcher.java:321)
at com.ibm.ws.webcontainer.extension.DefaultExtensionProcessor.handleRequest(DefaultExtensionProcessor.java:581)
at com.ibm.ws.wswebcontainer.extension.DefaultExtensionProcessor.handleRequest(DefaultExtensionProcessor.java:113)
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3391)
at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:267)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:811)
at com.ibm.ws.wswebcontainer.WebContainer.handleRequest(WebContainer.java:1455)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:115)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:458)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:387)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:267)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:136)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:195)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:743)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:873)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1473)
Changing the offending line to
writer.write(result != null ? result : "");
Solved the problem
For those of you trying to make this work directly from XHTML (instead of from XHTML generated from a JSP), there's an additional step that needs to be done.
You need to add a facelet-taglib (that is a ".taglib.xml") configuration for the faces tag.
If you don't do this, the tags are ignored by JSF.
Can you be more specific on the ".taglib.xml" that is needed? I use *.xhtml for all my pages. But do not know what ".taglib.xml" I seem to need. Where would I get this or create this from?
I really need some help here please.
I can NOT get the Principal username at all.
Mick,
The tablib.xml is already embedded inside the jar file you can download from this site. The jar file is acegi-jsf-1.1.3.jar. The tag library xml you will find inside the META-INF folder of the jar is acegijsf.taglib.xml file. If you follow the instructions under Detailed Steps section, then you can use
<acegijsf:authentication operation="username"/> to get the principal inside the JSF page.
Thanks, this helped me out alot :)
Hi, i receive a NPE when I use < acegijsf:authentication operation="username"/ > and I'm not logged. How can I solve this problem using JSF/Facelets?
Hi,
Is this new customized jar file available in in maven repository?
Thanks,
Anil.
You should use the tag only after you logged in or authenticated. The jar is not published in maven repository.
An example of using the tags that displays the username only when the user has a particular role. The following tag usage displays the user only if the user has either ROLE_USER or ROLE_ADMIN roles.
<acegijsf:authorize ifAnyGranted="ROLE_USER,ROLE_ADMIN">
Welcome, <acegijsf:authentication operation="username"/> | <a href="${request.contextPath}/spring/logout" title="Logout">Logout</a>
</acegijsf:authorize>
Thank you...I've done as you told and works ;)
I want the username in .xhtml file.
How I can get that?
I am trying as the the others said, but getting the same excepation.
Please help me?How to get this in .xhtml file
Atul
Do as Vigil said in the last comment...it works for me!
Thanks cecchisandrone
I am doing the same thing...cant get success.
I am using jdbc type implementation
I am passing the username and password, if they are valid then the role and username returns o.w.returns nothing.
I am checking if the user is active or not through query, if it is inactive it returns nothing not even role and the username is null so the error url shows on the same page "login.html/login_error=1"
I want that username to check wheather it is null for the inactive user to disaply the message
acegijsf:authorize ifAnyGranted="ROLE_USER,ROLE_ADMIN">
Welcome, acegijsf:authentication operation="username" | Logout
acegijsf:authorize
for this we need Role name, even we use
ifNotGranted = None of the roles must be granted for the user
I need that username .. even it is null
Atul,
What you need is an anonymous user role. Spring Security can display anonymous user name from the principal object provided, the user is granted privilege to use the page anonymously.
So define a new role something like ROLE_ANONYMOUS for the user you would like to see on the page. Then use only that role for the username using acegijsf tag (see my example).
The pages where you want authenticated user, use the real roles defined for the user in the database something like ROLE_USER or ROLE_ADMIN.
I hope this makes sense to you.
Regards,
Vigil
Vigil,
Thanks...
I solve the issue. What I do is, change the query, it return me the role. I check the role in acrgijsf tag.
Atul
Hi,
I've created a simple jar file to easily integrate Spring Security and Facelets. You can even add it as maven dependency.
Take a look at
Using Spring Security with FaceletsGreetings,
Dominik
Sorry, messed with the Link, it should be:Using Spring Security with FaceletsGreetings,
Dominik
Post a Comment