Foros de discusión

Simple custom auhtorization in JSF portlet

Jouni Latvatalo, modificado hace 9 años.

Simple custom auhtorization in JSF portlet

New Member Mensajes: 17 Fecha de incorporación: 21/10/13 Mensajes recientes
Hi,

I'm trying to figure out what would be the best way to implement a simple authorization feature in a faces portlet. In all its simplicity it could be something like:

1) Prerender, check if current conditions allow the user to see contents of portlet (or better yet, the whole page the portlet is on)
2a) If allowed, render normally
2b) If not allowed, redirect to login page

So far I've tried a preRenderView listener:

<h:head>
	<f:event listener="#{bean.isAllowed}" type="preRenderView" />
</h:head>


    public void isAllowed() throws IOException {
    	FacesContext.getCurrentInstance().getExternalContext().redirect("http://localhost:8080/c/portal/login");
    }


But this throws an exception:

javax.portlet.faces.BridgeException: javax.faces.FacesException: 6.1.3.1: Unable to redirect to a non-Faces view during the RENDER_PHASE


Then I tried to look how liferay internally handles it, and stumbled to PortalUtil.sendError. So I gave this a go:



@Named("MyBean")
@ViewScoped
public class MyBean extends BaseBean {

    @PostConstruct
    public void init() {
        if(isNotAllowed()) {
        	HttpServletResponse res = PortalUtil.getHttpServletResponse((PortletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse());
			HttpServletRequest req =  PortalUtil.getHttpServletRequest((PortletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest());
            try {
				PortalUtil.sendError(HttpServletResponse.SC_UNAUTHORIZED, new RolePermissionsException("Access denied"), req, res);
			} catch (IOException | ServletException e) {
				log.error("Unable to send error", e);
			}
        }
    }
}


This does prevent the actual portlet from rendering, but I still end up on the page wither headers and footers displaying. The following stacktraces are displayed in the log.


18:45:26,545 ERROR [http-bio-8080-exec-21][status_jsp:749] com.liferay.portal.RolePermissionsException: Access denied
com.liferay.portal.RolePermissionsException: Access denied
	at com.test.MyBean.init(MyBean.java:121)
	...
	stacktrace
	...
	and log messages from bean
	...
18:45:26,637 ERROR [http-bio-8080-exec-21][IncludeTag:129] Current URL /web/guest/my/url generates exception: null
java.lang.NullPointerException
	at org.apache.jsp.html.common.themes.portlet_jsp._jspService(portlet_jsp.java:592)
	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
	at com.liferay.portal.servlet.DirectRequestDispatcher.include(DirectRequestDispatcher.java:57)
	at com.liferay.portal.servlet.ClassLoaderRequestDispatcherWrapper.doDispatch(ClassLoaderRequestDispatcherWrapper.java:78)
	at com.liferay.portal.servlet.ClassLoaderRequestDispatcherWrapper.include(ClassLoaderRequestDispatcherWrapper.java:53)
	at com.liferay.taglib.util.IncludeTag.include(IncludeTag.java:295)
	at com.liferay.taglib.util.IncludeTag.doInclude(IncludeTag.java:192)
	at com.liferay.taglib.util.IncludeTag.doEndTag(IncludeTag.java:83)
	at org.apache.jsp.html.portal.render_005fportlet_jsp._jspService(render_005fportlet_jsp.java:1624)
	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
	at com.liferay.portal.servlet.DirectRequestDispatcher.include(DirectRequestDispatcher.java:57)
	at com.liferay.portal.servlet.ClassLoaderRequestDispatcherWrapper.doDispatch(ClassLoaderRequestDispatcherWrapper.java:78)
	at com.liferay.portal.servlet.ClassLoaderRequestDispatcherWrapper.include(ClassLoaderRequestDispatcherWrapper.java:53)
	at com.liferay.portlet.PortletContainerImpl._doRender(PortletContainerImpl.java:655)
	at com.liferay.portlet.PortletContainerImpl.render(PortletContainerImpl.java:138)
	at com.liferay.portlet.SecurityPortletContainerWrapper.render(SecurityPortletContainerWrapper.java:141)
	at com.liferay.portlet.RestrictPortletContainerWrapper.render(RestrictPortletContainerWrapper.java:126)


Ideas?

Edit: Using LR 6.2, faces 4.2.0-m2, weld cdi beans
thumbnail
Neil Griffin, modificado hace 9 años.

RE: Simple custom auhtorization in JSF portlet

Liferay Legend Mensajes: 2655 Fecha de incorporación: 27/07/05 Mensajes recientes
Hi Jouni,

Jouni Latvatalo:
(or better yet, the whole page the portlet is on)


I recommend that you set the permissions on the portal page so that only specific portal roles have the VIEW permission. That will take advantage of the out-of-the-box security provided by Liferay Portal. Consequently, you would not need to put that type of authorization check in your JSF portlets.

Kind Regards,

Neil
Jouni Latvatalo, modificado hace 9 años.

RE: Simple custom auhtorization in JSF portlet

New Member Mensajes: 17 Fecha de incorporación: 21/10/13 Mensajes recientes
Hey,

Neil Griffin:
I recommend that you set the permissions on the portal page so that only specific portal roles have the VIEW permission


This would obviously be the best way to go. However, the conditions that define whether a user is allowed to see the content or not, are quite complex and there are quite a few of them, so I'm not sure if I can map them to a reasonable amount of portal roles. At least not by hand. Creating the roles and adding them to the layouts programmatically might be an option...

I would still like to know what would be the best way to achieve something what I described in the original post. E.g. given set of conditions, redirect user to the login page (or any other page for that matter).

Br,
Jouni
thumbnail
Juan Gonzalez, modificado hace 9 años.

RE: Simple custom auhtorization in JSF portlet

Liferay Legend Mensajes: 3089 Fecha de incorporación: 28/10/08 Mensajes recientes
Jouni Latvatalo:
However, the conditions that define whether a user is allowed to see the content or not, are quite complex and there are quite a few of them, so I'm not sure if I can map them to a reasonable amount of portal roles. At least not by hand. Creating the roles and adding them to the layouts programmatically might be an option...


Hi Jouni,

sorry for insisting, but before investigating other options, can you describe your permission requirements and why Liferay OOB permission system doesn't fit into that?
Jouni Latvatalo, modificado hace 9 años.

RE: Simple custom auhtorization in JSF portlet

New Member Mensajes: 17 Fecha de incorporación: 21/10/13 Mensajes recientes
Hi Juan,

Thats ok emoticon The current functionality relies on an online integration with a backend system (ERP) and the values returned from the backend play a role in determining if the content can be shown to the user. So in order to use the OOB liferay permission system, I'd have to assign roles to the user and permissions to the layout every time we get a response from the backend, and that is something I'm a bit hesitant to do. Maybe for no reason?

-J
thumbnail
Juan Gonzalez, modificado hace 9 años.

RE: Simple custom auhtorization in JSF portlet

Liferay Legend Mensajes: 3089 Fecha de incorporación: 28/10/08 Mensajes recientes
Hi Jouni,

interesting...Have you though in integrating your ERP with Liferay's permission system? This way you would benefit from many advantages: performance (as permissions get cached), flexibility and separation between those two systems.

If you already have some custom entities in Liferay that are going to be queried from your ERP, maybe you can simply invoke Liferay permission webservices from your ERP whenever those entities/permissions are modified. In that case, you simply can focus on your Liferay portlets, because you are using the builtin permission system.

There are other options, like adding some ServicePreAction hooks, but this solution would definitely lead to a poor performance, as you should query your ERP everytime.
Jouni Latvatalo, modificado hace 9 años.

RE: Simple custom auhtorization in JSF portlet

New Member Mensajes: 17 Fecha de incorporación: 21/10/13 Mensajes recientes
Hi,

We have an Active Directory integration on the roadmap, but not in the nearest future. This will hopefully address some of the issues raised here. Until that project is finished, we'll be needing another way to handle this.

ServicePreAction hook could be something to consider if we can somehow figure out which portlet (or layout) initiated the request. Then we'd only trigger the permissions checks if it came from a portlet / layout that potentially needs authorization.

-J
thumbnail
Neil Griffin, modificado hace 9 años.

RE: Simple custom auhtorization in JSF portlet

Liferay Legend Mensajes: 2655 Fecha de incorporación: 27/07/05 Mensajes recientes
Regarding integration possibilities, I just wanted to point-out the following lines from portal.properties:

    #
    # Set the default permission checker class used by
    # com.liferay.portal.security.permission.PermissionCheckerFactory to check
    # permissions for actions on objects. This class can be overriden with a
    # custom class that implements
    # com.liferay.portal.security.permission.PermissionChecker.
    #
    #permissions.checker=com.liferay.portal.security.permission.SimplePermissionChecker
    permissions.checker=com.liferay.portal.security.permission.AdvancedPermissionChecker