Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » scout » create permission
create permission [message #732220] Tue, 04 October 2011 05:26 Go to next message
Li Hao is currently offline Li Hao
Messages: 28
Registered: August 2011
Junior Member
I read the howto on the create permission, but don't quite get it.

The server has an auto-generated class AccessControlService, I try to load the permission from database. Do I need to overwrite the auto-created execLoadPermissions()

protected Permissions execLoadPermissions() {
Permissions permissions = new Permissions();
permissions.add(new RemoteServiceAccessPermission("*.shared.*", "*"));
//TODO fill access control service
permissions.add(new AllPermission());
return permissions;
}

Is there any more detail example on the permission?
Re: create permission [message #735613 is a reply to message #732220] Wed, 12 October 2011 07:43 Go to previous messageGo to next message
Daniel Wiehl is currently offline Daniel Wiehl
Messages: 21
Registered: April 2010
Junior Member
You are absolutely right. In order to make the system aware of your database permissions you have to overwrite AccessControlService#execLoadPermissions().

In the following, I will give you some more detail on how access control works in Scout.

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
Overwrite the method execLoadPermissions in your AccessControlService. 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.

Fine-grained access control

Further, it is possible to use fine-grained access permissions. This is in contrast to the BasicPermission mentioned above, which simply handles 'go' or 'no-go' situations. That is that if the user has the permission, the access to the resource is granted or rejected otherwise.

However, fine-grained access permissions must be of the type BasicHierarchyPermission. Furthermore, 'PERMISSION_LEVEL' in the database table 'ROLE_PERMISSION' comes into play, meaning that in there, you specify the access level on its behalf the user can access protected resources.
The concept is based on various levels in the range from 0 up to 100. Thereby, 0 means no-access, whereas 100 mean full-access. Basically, if the permission of the user (loaded from database) has a level higher or equals than/to the level requested, access is granted.
In BasicHierarchyPermission, the following levels are defined:

LEVEL_NONE = 0
LEVEL_ALL = 100
LEVEL_UNDEFINED = -1


Again, let us elaborate a tiny example:
The requirement would be that users should only access companies which they really belong to. For that purpose, we introduce a new access level LEVEL_OWN=10.

The permission ReadCompanyPermission would be changed as follows:

public class ReadCompanyPermission extends BasicHierarchyPermission {
  
	public static final int LEVEL_OWN = 10;
  
  private Long m_companyId;
  
  public ReadCompanyPermission(Long companyId) {
    super("ReadCompany" + "." + companyId, LEVEL_UNDEFINED);
    m_companyId = companyId;
  }
  
  protected boolean execCheckLevel(int userLevel) throws ProcessingException {
 		if (userLevel == LEVEL_OWN) {
 			return SERVICES.getService(ICompanyService.class).isOwnCompany(getCompanyId());
 		}
 		return false;
  }
  
  public Long getCompanyId() {
  	return m_companyId;
  }
}


In order to enable fine-grained access control so the user can only access his personal company objects anymore, the user's permission level must be changed to 10 in ROLE_PERMISSION.PERMISSION_LEVEL for the permission 'ReadCompanyPermission'.

The access-check to protect the company resource would be changed as follows:

if (!ACCESS.check(new ReadCompanyPermission(xy))) {
   throw new VetoException("Authorization failed");
} else {
   // user is authorized, do some business logic here
}


As you may have noticed, there is provided an implicit level in the ReadCompanyPermission's constructor when doing the super call. This level stands for the minimal required level the user must have in order to access the resource. If you would put LEVEL_ALL in there, the user would not be allowed to access the company resource anymore as his level is only 10 (LEVEL_OWN) which is lower than 100 (LEVEL_ALL).
In difference, the level LEVEL_UNDEFINED (-1) does not represent a concrete level, but exclusively stands for fine-grained access control. As a consequence, the access controller does not decide by itself whether to grant access or not. Thereto, it delegates this decision to you by invoking execCheckLevel(int userLevel) on the permission.

In this example, the provided userLevel would be 10 (LEVEL_OWN). That indicates your code that the caller is only allowed to see companies which he belongs to.
In consequence, you have to verify the user's relation to the given company and grant access accordingly.

So feel free to define some other fine-grained access levels, e.g. LEVEL_DEPARTMENT = 20;

Please note, that by calling ACCESS.getLevel(Permission p) the user specific access level on that permission can be requested.

If you have any further questions, please feel free and let us know.
Re: create permission [message #735755 is a reply to message #735613] Wed, 12 October 2011 12:22 Go to previous messageGo to next message
Claudio Guglielmo is currently offline Claudio Guglielmo
Messages: 126
Registered: March 2010
Senior Member
Hi Dani

Great explanation! Could you please add that stuff to the wiki?

Please create a howto but also extend the documentation, there is already a section prepared: http://wiki.eclipse.org/Scout/Documentation#Granting

Please don't mix them up. The documentation should explain the concepts and the howto should show how to use them.

Thanks
Claudio
Re: create permission [message #735841 is a reply to message #735755] Wed, 12 October 2011 16:51 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie Bresson
Messages: 117
Registered: November 2010
Senior Member
Claudio Guglielmo wrote on Wed, 12 October 2011 18:22
Great explanation! Could you please add that stuff to the wiki?


To my mind this how to belongs to:
Scout > HowTo > Use permissions in your Scout application

[Updated on: Thu, 13 October 2011 07:24]

Report message to a moderator

Re: create permission [message #753063 is a reply to message #732220] Wed, 26 October 2011 12:12 Go to previous message
Claudio Guglielmo is currently offline Claudio Guglielmo
Messages: 126
Registered: March 2010
Senior Member
Documentation is updated.

See http://wiki.eclipse.org/Scout/Concepts/Security

Regards
Claudio

[Updated on: Tue, 01 November 2011 15:41]

Report message to a moderator

Previous Topic:Security with JAAS
Next Topic:Remove unused translations ?
Goto Forum:
  


Current Time: Tue Jul 22 11:30:43 EDT 2014

Powered by FUDForum. Page generated in 0.03508 seconds