Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Scout/HowTo/3.8/Use permissions in your Scout application
The Scout documentation has been moved to https://eclipsescout.github.io/.
How to use permissions in your Scout application
1. Create AccessControlService to load your permissions
First of all, create a custom access control service which inherits from AbstractAccessControlService
. This is typically created by Scout SDK itself. Furthermore, this service has to be registered in plugin.xml similar to:
<service class="x.y.server.services.custom.security.AccessControlService" factory="org.eclipse.scout.rt.server.services.ServerServiceFactory" session="x.y.server.ServerSession" />
2. Load permissions from database
Add some logic for the The Scout documentation has been moved to https://eclipsescout.github.io/. event of your AccessControlService
(by overwriting the execLoadPermissions
method): there you load all the permissions that belong to the user of the given context.
Let us say you have a role based security concept with the 2 database tables USER_ROLE AND ROLE_PERMISSION. In the table USER_ROLE, there you link the user to several roles whereas the table ROLE_PERMISSION holds all the permissions that belong to those roles.
By running the following SQL statement, you get all the permission that belong to the given user:
Object[][] permissionData = SQL.select("" + "SELECT P.PERMISSION_NAME, " + " P.PERMISSION_LEVEL " + "FROM USER_ROLE R " + "LEFT JOIN ROLE_PERMISSION P " + " ON P.ROLE_ID = R.ROLE_ID " + "WHERE R.USER_ID = :userId");
In turn, you call AccessControlUtility.createPermissions(permissionData)
to create the associated Java permissions.
Last but not least, you add the permission RemoteServiceAccessPermission
to the collection of permissions to allow the user to call backend services. The two arguments allow you to constrain the kind of services this user is allowed to call. You can use the wilcard character *
to specify a matching pattern.
All in all, your AccessControlService
looks as follows:
public class AccessControlService extends AbstractAccessControlService { @Override protected Permissions execLoadPermissions() { Object[][] permissionData = SQL.select("" + "SELECT P.PERMISSION_NAME, " + " P.PERMISSION_LEVEL " + "FROM USER_ROLE R " + "LEFT JOIN ROLE_PERMISSION P " + " ON P.ROLE_ID = R.ROLE_ID " + "WHERE R.USER_ID = :userId"); Permissions p = AccessControlUtility.createPermissions(permissionData); p.add(new RemoteServiceAccessPermission("*.shared.*", "*")); return p; } }
Please note: There exists the permission AllPermission which implies all other permission. For full-access, please add this permission to the collection.
3. Create java.security.Permission representatives
All the permissions you like to have available in your application must be represented by a 'java.security.Permission' permission. Let us assume you require a permission to allow a user to access companies. Thereto, you create the permission class ReadCompanyPermission
in the package x.y.shared.security
:
public class ReadCompanyPermission extends BasicPermission { public ReadCompanyPermission() { super("ReadCompany"); } }
The name you provide in the constructor is the name of the permission. Among other things, its is used to decide whether to grant access to a specific resource. For more detail, please refer to BasicPermission#implies(Permission p)
which is evaluated in IAccessControlService#checkPermission(Permission p)
.
4. Populate database tables ROLE_PERMISSION AND USER_ROLE
Put an entry into the table ROLE_PERMISSION to represent this permission. Also, create a role entry to associate this permission with a role the user belongs to. Please note, that in the example above, the PERMISSION_NAME would be x.y.shared.security.ReadCompanyPermission
. The level is not of interest for this kind of permission, so simply put PERMISSION_LEVEL=100
. More on the topic 'level' will follow further down.
5. Protect resources
Finally, you're done. In your business logic, you now can check for that permission. This is done as follows:
if (!ACCESS.check(new ReadCompanyPermission())) { throw new VetoException("Authorization failed"); } else { // user is authorized, do some business logic here }
Please note, that the class ACCESS
is simply a delegate to IAccessControlService
.
In the following, please find some more information about the topic.
How permissions are discovered
Permission are discovered by IPermissionService. The default implementation looks for permission classes in all bundles installed in the OSGi environemnt. Thereby, the following criteria must be satisfied:
- The class must be of the type java.security.Permission
- The type must be a public concrete class, meaning not an interface nor an abstract class
- Class must have the token Permission in its name
- The class must be located in a package with .security. in its package path
Please note: This behavior can be overwritten by writing an own implementation for IPermissionService
.