At ICON UK I was talking to another developer about methods of restricting access to data in XPages. Historically, when I started with XPages my approach was probably one most people use, ACL-driven – readers fields, roles and the “acl” property on an XPage. But as I started digging deeper with ODA and using more imaginative approaches to application access, I started breaking out of the traditional Notes approaches to restricting access.

The strength of XPages and other server-side frameworks is that everything can be tied down before any data or HTML is generated. And this has tended to be my approach now, a more conceptual approach, particularly with web applications where the users don’t have Notes Client access or Notes IDs. At the same time, most of my applications now use an MVC approach based on an early version of Jesse Gallagher’s XPages Scaffolding project.

This uses a ViewHandler, extending com.ibm.xsp.application.ViewHandlerExImpl class. The key method here is createView(), which calls ViewHandlerExImpl.createView(). As I’ve mentioned before, the XPage you code is not what’s run. Instead, there’s a Java class that you can find in the Package Explorer view, in the Local>xsp folder

It’s this which ViewHandlerExImpl.createView() uses to initialise the XPage “ViewRoot” and create the viewScope. This means you can run code even before the XPage is initialised, before beforePageLoad runs, which can check access and prevent access to unauthorised XPages at the earliest possible point in the page lifecycle.

As I mentioned, before super.createView() viewScope doesn’t exist. So our controller class “pageController” is put in requestScope at line 130 and “moved” to viewScope in line 143 and 144. It’s important to remember EL searches for that variable name everything from the smallest scope up to the biggest. The biggest could be serverScope, as created in ODA, but the smallest will be smaller than requestScope. It could be a Panel or a Repeat Control with dynamic runtime binding, as Tim Tripcony taught us in his blog post “The reason panel data sources can’t be accessed outside the panel“. So we can still use #{pageController.myProperty} on an XPage regardless of whether it’s used when creating the view or later in the lifecycle.

In lines 132 and 133 I load into the pageController whether the user has specific roles. Then from line 134 I check if the user is admin and if this page has Admin in the pageName. If it’s an admin page and the user isn’t an admin, I redirect them to the home page. This means there’s no way for a user who’s not admin to get to an admin page. I don’t need to add anything to the specific XPage. I just need to use a standard naming convention for the page,and my application automatically handles it.

And it can be extended for other groups of pages. For example, I’ve used it for users who needed access to all documents but were only allowed to do restricted thing and see restricted information. In terms of the ACL, they have full access. In terms of the application, they have restricted access. And because they don’t have Notes IDs, the application restriction is acceptable.

Incidentally, the important of understanding scoping is why, unlike others, I think the scope maps (applicationScope, sessionScope, viewScope and requestScope; plus userScope, identityScope and serverScope in ODA) are good practice. Managed beans have been encouraged as better practice, but remember they are also added to one of those four basic scopes. I don’t think it would work to set the scope to one of the ODA scopes like serverScope. The problem isn’t the use of scopes, it’s not understanding what the scopes are and not thinking conceptually of a component and the scope in which it sits.

4 thoughts on “Restricting Access to XPages”

    1. It intercepts the code earlier, but can also allow greater flexibility. So it could prevent access e.g. based on deadlines (not that I’ve had that need).

  1. Ah, breaking away from Notes is when things start making sense, even security (although sessionAsSigner is so far from perfect… barely decent at best)

    I picked that habit of extending the ViewHandler to instantiate a viewScoped controller for the page but little by little I shied away from it to the point that now I’m only using it to apply some complex logic for the locale used (overriding the calculateLocale method). What you say is correct, you can check anything at the earliest stage, there’s an advantage there, but that place isn’t fully baked as you yourself acknowledge – absence of viewScope.

    I shied away from it when I started embracing more and more the concept that there should be a properly named bean for everything – a more horizontal than vertical approach to “making the page work” – and the more correct way such beans should be declared and called.

    For starters, not all pages require the same kind of check. Again, at first I created an interface with a method destined to be called from the ViewHandler side of things that all page controllers implemented. The ViewHandler would call the interface method and therefore perform whatever check was needed on a class by class basis without polluting the ViewHandler with specific code. Then something started itching me: not all my pages required a controller to be functional (considering the approach of taking advantage from a collections of beans that do different things), and yet the check for whether the class existed was made anyway, and secondly and importantly as well using the same `pageController` variable name everywhere impaired my ability to see at glance what viewScoped bean was the EL declaration referring to (also useful when you need to do renaming operations).

    So now all the beans are declared in the faces-config.xml, like it should for those poor souls that have nothing better than an old and clunky JSF framework at hand – and every needed check takes place through the use of the beforePageLoad attribute on the xsp itself (#{pageRegister.beforePageLoad} or #{pageAccounts.beforePageLoad} etc…). My goal is always to avoid cluttering these page oriented beans with unnecessary code that doesn’t belong to the very specific logic of the page. All the rest is supplied by other kinds of bean.

    So, the bottom line is that beforePageLoad is still very early in the life-cycle and I can more precisely control when to use it or not. There’s only one problem: the presence of any custom controls on the page must be dealt with. Those things get evaluated even when a redirect is taken place. My solution is to wrap the outermost container with a loaded property that gets flipped to false in the calling of beforePageLoad method for the page if, for any reason, the loading of the page must be interrupted (by the absence of proper permissions for example)

    1. I’ve become quite laid-back in my approach. At the end of the day, whether it’s a controller, a POJO, a managed bean, a model object using Tim Tripcony’s SmartDocumentModel, or a DominoDocument datasource, it’s always a Java object stored in a scope which, unless you do something specific, the XPages runtime will always clean up based on timing or number of xp:views in memory or on disk. My controllers typically contain other objects (specific to the page or loaded from sessionScope) and also have the usual beforePageLoad, beforeRenderResonse etc methods thanks to Jesse’s work. I often use DominoDocument and DominoView datasources on the XPage itself because, if they do what I need, there’s no point reinventing the wheel. The key is ensuring the code is written once, in the most sensible place, and refactored when appropriate. If it minimises bugs and make support / extensibility easy, I’m happy.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.