> -----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.