Permissions design pattern that allows date-based

2019-05-31 15:03发布

问题:

I am looking at ways to implement an authorization (not authentication) scheme in my app.

There are currently two roles in the system: A and B, but there may be more. User's only have one role.

Basically, the I have it set up now is with two database tables. One is for role-based permissions on a model, and the other is for specific user-based permissions. I am thinking that this way, users can have a set of default permissions based on their role-based permissions, but then they can also have specific permissions granted/revoked.

So for example:

table: user_permissions
columns:
    user_id: [int]
    action: [string]
    allowed: [boolean]
    model_id: [int]
    model_type: [string]

table: role_permissions
columns:
    role: [int]
    action: [string]
    model_type: [string]        

In the user_permissions table, the allowed field specifies whether the action is allowed or not, so that permissions can be revoked if this value is 0.

In another table, I have the definitions for each action:

table: model_actions
columns:
    action: [string]
    bitvalue: [int]
    model_type: [string]

I do this so that when I check permissions on a model, for example ['create', 'delete'], I can use a bitwise and operation to compare the user's permissions to the permissions I am checking. For example, a model X could have the following model_actions:

action: 'create'
bitvalue: 4
model_type: X

action: 'delete'
bitvalue: 2
model_type: X

action: 'view'
bitvalue: 1
model_type: X

If my user/role permissions specify that the create, view, and delete actions for the model X are 1, 0, and 1, respectively, then this is represented as 110 based on the model_actions table. When I check if I can create model X, I use the fact that create is 4 to construct the bitarray 100. If the bitwise AND operation of 110 and 100 is 100, then the permission is valid.

ANYWAY, I think I have a granular permissions design pattern figured out. If not PLEASE feel free to educate me on the subject.

The actual focus of my question concerns the following:

Some of my models have actions that are time-dependent. For example, you can only delete a model Y no more than 24 hours after its created_at date.

What I am thinking is to automatically create a cron job when the model is created that will update the permissions on the date that this occurs. In the case of model Y, I would want to insert a record into the user_permissions that revokes the 'delete' action of this model.

My question is: is this advisable?

Edit

What if I include another row in the SQL tables, that specifies a date for the permission to 'flip' (flipDate)? If a flipDate is defined, and if the current date is after the flip date, the permission is reversed. This seems much easier to manage than a series of cron jobs, especially when models may be updated.

回答1:

Your models seems fine, but... you are reinventing the wheel a bit and, as you realized yourself, your model is not flexible enough to cater for additional parameters e.g. time.

In the history of authorization, there is a traditional, well-accepted model, called role-based access control (RBAC). That model works extremely well when you have a clearly defined set of roles and a hierarchy between these roles.

However, when the hierarchy isn't as clear or when there are relationships (e.g. a doctor-patient relationship) or when there are dynamic attributes (such as time, location, IP...), RBAC doesn't work well. A new model emerged a few years back called attribute-based access control (ABAC). In a way, it's an evolution or generalization of RBAC. With ABAC, you can define authorization logic in terms of attributes. Attributes are a set of key-value pairs that describe the user, the action, the resource, and the context. With attributes, you can describe any number of authorization situations such as:

  • a doctor can view a patient's medical record between 9am and 5pm if and only if the patient is assigned to that doctor
  • a nurse can edit a patient's medical record if and only if the patient belongs to the same clinic as the nurse.

ABAC enables what one could call PBAC or policy-based access control since now the authorization logic moves away from proprietary code and database schemes into a set of centrally managed policies. The de-facto standard for these policies is XACML, the eXtensible Access Control Markup Language.

In a nutshell, XACML lets you do what you are looking for in a technology-neutral way, in a decoupled, externalized way. It means, you get to define authorization once and enforce it everywhere it matters.

I recommend you check out these great resources on the topic:

  • NIST's website on RBAC (the older model)
  • NIST's website on ABAC (the model you need)
  • the OASIS XACML Technical Committee website (the standard that implements ABAC)
  • Gartner's Externalized Authorization Management
  • Kuppinger Cole's Dynamic Authorization Management
  • The ALFA plugin for Eclipse, a tool to write attribute-based policies.