> -----Oprindelig meddelelse-----
> Fra: Shawn McKinney [mailto:[email protected]]
> Sendt: 5. november 2015 17:25
> Til: [email protected]
> Emne: Re: Repository of Permissions / Permission public setters
> 
> 
> > On Nov 5, 2015, at 2:52 AM, Jan Sindberg <[email protected]> wrote:
> >
> > Each permission will have to be checked more than one place. Multiple
> places when generating the GUI - not to show fields, buttons, action-menus,
> or even complete lists of "assets". But still malicious users could have
> knowledge of the direct action-urls and therefore all related serverside
> methods must be access-checked (similar to javascript validation must be
> repeated serverside).
> >
> > I want to centralize in order to :
> > 1) Have only one place to do changes in case an object or operation name
> changes or is misspelled.
> > 2) Creating better semantics in the access-check.
> > 3) Having better code-completion and refactoring help in the IDE (Eclipse,
> Intellij, etc.)
> > 4) Making it easier to find all permissions related to a specific object.
> >
> > Looking at Role Engineering, it seems to me that it is a good practice to
> center roles and operations around objects. When trying to think about our
> domain, it makes good sense (for me) to group permissions around the
> object they are related to.
> > So my example is about ease of use and understanding our domain. Ease of
> coding, refactoring and extending. Reducing the risk of making errors and
> centralizing error-correction.
> >
> > Just getting an idea. If I can get hold of the accessMgr and the session
> globally, I could even do like this.
> > If (Permission_Letters.checkEditDamageLetters()) {
> >    // Do stuff
> > }
> >
> > (assuming I can get to the accessMgr and the session inside the checkXXX-
> method)
> 
> OK, I am tracking with you now and yes your ideas makes good sense to me.
> Now, for my next question, would a new permission wrapper class or
> extension to the accessmgr help here?

Well, it is mostly a question of personal taste, architectural style and secure 
programming. If a Permission is really a value-object, then it should be 
immutable once created (personal opinion). I could use annotations to make my 
objects immutable. 
I show my own wrapper below.

> 
> Regarding your question about using/storing manager and session objects
> globally…
> 
> All of the manager objects are threadsafe, may be created, held, and reused
> across multiple thread contexts without concern.  On the other hand, they
> are also relatively cheap to create, so no real concern if you want to create
> and throw them away on every usage.
> 
> One word of caution wrt multienancy - manager’s are scoped to a single
> tenant, and your usages need to be aware of that scoping, if processing in a
> multitenant context.
> 
> The session object is not thread safe (like all other fortress entities) so 
> bear
> that in mind as you build your system.
> 
> Hope this helps,
> 
> Shawn

Still new to session management and thread issues. I am looking at Shiro and 
consider if I want to use that as API and Apache Fortress as Realm. Shiro 
handles sessions and also allows multiple Realms.
Here is what my current homebrew experiment looks like.:

// Singleton to hold instances
// setPrincipal should be called where users are logged in and out.
public class SecurityUtil
{
  private static SecurityUtil ourInstance = new SecurityUtil();
  ThreadLocal<Principal> infoThreadLocal = new InheritableThreadLocal();

  public static SecurityUtil getInstance()
  {
    return ourInstance;
  }

  private SecurityUtil()
  {
  }

  public void setPrincipal(Principal _principal)
  {
    this.infoThreadLocal.set(_principal);
  }

  public Principal getPrincipal()
  {
    return (Principal) this.infoThreadLocal.get();
  }

  /**
   * Todo
   * @return
   */
  public boolean initializePrincipal()
  {
    return false;
  }
}

// The principal holds the session and the accessMgr.
// This allows for each principal to have individually configured accessMgr.
// You might want to subclass this to add you own user object, etc.
public class Principal
{
  private AccessMgr accessMgr;
  private Session session;

  protected AccessMgr getAccessMgr()
  {
    return accessMgr;
  }

  protected void setAccessMgr(AccessMgr _accessMgr)
  {
    accessMgr = _accessMgr;
  }

  public Session getSession()
  {
    return session;
  }

  public void setSession(Session _session)
  {
    session = _session;
  }

  // Should not be used outside this package
  // See PermissionObject
  public protected checkAccess(Permission _permission)
  {
    // Do audit log ?
    //...

    boolean result = false;
    if (session.isAuthenticated())
    {
      try
      {
        result = accessMgr.checkAccess(session, _permission);
      }
      catch (org.apache.directory.fortress.core.SecurityException e)
      {
        e.printStackTrace();  //todo
      }
    }
    return result;
  }
}

// A simple class to express a permission with an operation
public class PermissionObject
{
  private String objName;
  private String opName;
  private Permission permission;

  public PermissionObject(String _objName, String _opName)
  {
    objName = _objName;
    opName = _opName;
    permission = new Permission(_objName, _opName);
  }

   public boolean authZ()
   {
     boolean result = false;
     Principal principal = SecurityUtil.getInstance().getPrincipal();
     if (principal != null)
     {
       result = principal.checkAccess(permission);
     }
     return result;
   }

  public boolean authZ(String _objId)
  {
    boolean result = false;
    Principal principal = SecurityUtil.getInstance().getPrincipal();
    if (principal != null)
    {
      result = principal.checkAccess(new Permission(objName, opName, _objId));
    }
    return result;
  }
}

// A collection of permissions.
// This is the application or domain specific permissions to be used
public class FMPerm_Letters
{
  private static String name = "LETTERS";
  public static final PermissionObject EDIT_CONSIGNMENT_LETTER = new 
PermissionObject(name, "EDIT_CONSIGNMENT_LETTER");
  public static final PermissionObject EDIT_WITHDRAWAL_LETTER = new 
PermissionObject(name, "EDIT_WITHDRAWAL_LETTER");
  ....
}

// A very simplified example of usage
public class SomeDataObject {

  public Button getEditConsignmentLetterButton()
  {
     If (EDIT_CONSIGNMENT_LETTER.authZ()) {
         return ButtonBuilder.getEditConsignmentLetter();
     }
     else {
        return null;
     }
  }
}

A nicer solution would be to use annotations on the getter-methods instead. But 
that's an example for another time. The inner workings of the annotation would 
be somewhat similar but determining return value by reflection and application 
specific requirements.


Reply via email to