Using declarative permissions is the preferred way to have security constraints on GUI elements, separately from business logic and fine-grained because we are using individual permission/access rights.
With JavaServer Faces, you can add custom tags, but also within JavaFX FXML views you can do something similar. And recently I found the time to create a POC for an idea that I had some years ago.
When defining indications within the view of your application, GUI elements can be active or not visible depend ending on the permissions the user has. By placing them within your view markup you have 2 major benefits:
- The ‘definition’ when an element should be visible is done on the element itself and thus it is very clear on which element it operates
- It isn’t mingled with your other business code.
Also, using permissions is much better and easier to work with than roles. When each feature is assigned specific permissions which the user needs to have, no application redeploy is needed when a feature can now be used by more users. You just have to assign the permission to the users.
Roles are assigned to users and thus when a single feature needs to be accessible by a group of people, you can’t assign the role to them as it would give them also access to other features. And thus you end up changing the code.
With the FXML views, you can define how the view is presented to the end users. Just as with JavaServer Pages tags, it is also possible to create your own custom components to tailor the system to your needs.
Adding additional information to the standard components is also possible by means of the userData tag.
<Button mnemonicParsing="false" onAction="#permission" text="Only admin permission"> <userData> <RequiresPermissions value="admin"/> </userData> </Button>
You can add there information which can be used by your code later on. You can even add multiple data sets by using the JavaFX Collections.
Here in our case we add an instance of the Octopus JavaFX RequiresPermissions class and specify that the user needs the permission admin before the button will be visible.
In order to make this work, you need also to import the class (just as within regular java code)
Processing the view
In order to remove the component from the view when the user hasn’t the required permissions, we need to scan the view just before it is ‘rendered’ to the screen.
This can be easily achieved by the excellent framework afterburner which was a method getView() defined within the FXMLView class.
Octopus defines a child class, be.atbash.ee.security.octopus.javafx.SecureFXMLView, which performs the following steps when the view is retrieved
- Scan all view nodes
- Verifies if there is an instance of the RequiresPermissions within the userData section
- Checks if the user has the permission or not.
- If (s)he has not, sets the node to not visible (node.setVisible(false) )
Octopus Java FX support
Next, to the processing of the view, Octopus has now also support for JavaFX views by helping the developer in creating a Login screen and the integration with the Octopus Core classes which can perform the required steps for authentication and authorization.
This support is built on top of the afterburner framework which makes developing JavaFX applications easy.
You can start the application by using the start method from the be.atbash.ee.security.octopus.javafx.SecureFXMLApplication class.
SecureFXMLApplication.start(stage, new LoginView(), new UserPageView());
The loginView itself must extend from be.atbash.ee.security.octopus.javafx.LoginFXMLView and contain components with ids user, password and loginButton.
The start() method must also a receive an instance of the first real page which will be shown after the user is authenticated. This is a FXML view where the java class extends from be.atbash.ee.security.octopus.javafx.SecureFXMLView. These views are scanned for their contents within the userData section and component are hidden when the user doesn’t have the required privileges.
Page navigation can be performed by be.atbash.ee.security.octopus.javafx.SecureFXMLApplication#showPage and this method also perform the hiding of components based on the authorization info of this view.
The Atbash Octopus framework code has a demo application to show this feature in action. It can be found at GitHub .
For those who want to have a quick idea how it looks like, I recorded also a short video which demonstrates the demo
Declarative permissions can also be used on JavaFX FXML views, just as you can do this with JavaServer Faces. Instead of custom tags who defines the required permissions, you have to define the permission requirements within the userData section which is available within each JavaFX component.
This is only a POC and the functionality will be extended in future versions of Atbash Octopus (as the rewrite of the Octopus framework is currently still in Alpha)
Have fun with it