依靠角色来限定的访问控制
As a role is primarily a behavioral concept, the logical step when developing software is to use Roles as a means to control access to application features or data. As you might expect, most people call this approach Role-Based Access Control, or RBAC (“are-back”) for short.
角色权限非常重要,现在我们使用权限控制来编写软件以来控制软件和数据的访问安全。如你所知的那样,大部分人称这为角色-基础-访问控制 ,或者RBAC。
However, there are two primary ways of of actually implementing and performing Access Control: an Implicit way, and an Explicit way.
如我们所知道的,现在有两种不同的方式去实际实现这个:隐式实现和显式实现。
The very large majority of software applications today use Implicit access control. I posit that ExplicitAccess Control is much better for securing today’s software applications.
现在对于任何的软件应用,我们都使用隐式权限控制。但是我认为显式的权限控制对于今天的软件应用来说更加的优秀
Implicit Access Control
As mentioned previously, Roles represent behavior or responsibility. But how do we know exactly what behavior or responsibility is associated with a role?
隐式访问控制:
就像之前强调过的,角色代表了用户的行为或权限,但是我们如何去了解到底哪个行为或权限是归属于这个角色的呢
The answer is that, for the large majority of applications, you don’t know exactly what that role represents. You have a good idea of course – you know that someone with an ‘administrator’ role can probably lock user accounts or configure certain parts of the application, and maybe user accounts assigned the ‘customer’ role can put items in a shopping cart or request new products. But usually there is nothing that concretely defines what those behaviors are.
答案是:对于大部分的应用,你不会了解那些角色代表了什么。你大概会知道一些人大概是aministrator ,一个可以锁住其他用户的角色,并且也能配置应用的一些部分。也有可能是一个“customer”的角色,一个可以放置商品进购物车或者请求新产品,但是一般来说并没有非常明确的定义关于这些行为
Take for example the string “Project Manager”. It is just a string name – there is nothing else about it that a software program can inspect to find out “based on this name, I know users assigned this role can do X, Y and Z”. Developers typically program their applications using this name alone. For example, to see if a user is allowed to view project reports, you’ll typically see code like this:
我们举一个例子比如“project manager”,这只是一个普通的字符串名称,对于应用程序来说,从这个名字并不能得出任何的信息关于“这个用户可以做什么,例如 A ,B, C”程序员经常只是使用这个名字来编写他们的代码。举例说明如果用户用看项目报告,你会看到如下面的代码:
//Listing 1. Example Implicit Role-Based Access Control security check: if (user.hasRole("Project Manager") ) { //show the project report button } else { //don't show the button }
In this example code block, the software developer made the decision to show a button or not based on the ‘Project Manager’ role (probably a project requirement). But notice that nothing in the code above actually explicitly says “the Project Manager role is allowed to view project reports”. No one defined that behavioral statement anywhere in software – it is implied that ‘Project Manager’ users can view project reports, so the developer writes an if/else statement reflecting that assumption.
在这个示例的代码模块,程序员通过这个“project manager ”角色(也许是一个项目的需求)来决定是不是来展示这个按钮。但是你得知道,这里并没有任何的代码说明“project manager”角色可以看项目报告。这个代码的任何部分都没有定义,“project manager”可以看项目报告,所以这里程序员用IF/ELSE 去反应这个假设。
Brittle Security Policy
Security access control like the above example is very brittle. That is, it is likely to break, fail, or cause inefficiencies with even slight changes to security requirements.
To illustrate, let’s assume that the team writing the software is told “oh, by the way, we need a new ‘Department Manager’ role, and they also need to be able to view project reports. Make it happen”.
Now the software developer needs to go back into code to change it to be like this:
非常脆弱的安全政策
像上文的访问安全控制是非常脆弱的,这种实现方法非常容易失败,被破坏,或者非常轻微的安全度变化也效率极低,
为了举例说明,我们假设团队正在写一个软件要求为“顺便,我们需要一个新的 “department manager”角色,这个角色也需要能够阅读全部的项目报告,实现这个。
现在这些码农需要回去并且改变他们的代码如下面:
//Listing 2. Example Modified Implicit Role-Based Access Control security check: if (user.hasRole("Project Manager") || user.hasRole("Department Manager") ) { //show the project report button } else { //don't show the button }
Then the developer needs to update his test cases, re-build the software, go through whatever QA processes exist, and schedule re-deployment to production – all because of a relatively trivial new security requirement.
But what happens if management returns and asks for another role to be able to view reports? Or if they need to remove that ability later on?
现在这些码农需要更新他们的测试实例,重构整个软件,更新他的QA进程,并且制定日程重新去产品。全部因为这个一个新的安全权限要求。如果管理回来并且要求新的权限。唯一的解决办法是重新再写一个
Or, what if the software needs to support the ability to dynamically create or remove roles at runtime because they want customers to be able to configure roles themselves?
In any of these scenarios, the common implicit (static string) Role-Based Access Control approach fails to meet security needs. If security policies change, it would be ideal if you didn’t need to touch source code at all. It would be ideal that the source code only needs to change when data model requirements deem necessary.
或者这个软件有可能会需要支持用户动态修改他们的权限,在任何这种类型的普通的公共隐式(静态字符串) Role-Based Access Control approach 失败于满足这个安全需求,如果安全需求改变了,不用改变源代码的方法才是最好的。最好是源代码只在需要改变数据模型的时候才会要改变。
Explicit Access Control: A Better Way
As we see above, changing security policies with an implicit access control approach can wreak havok on software development. It would be a lot nicer if security policy changes didn’t force code refactoring. Ideally, it’d be really nice if security policies can be changed while the application is running so you don’t impact your end-users. This is even better for security too, because if you see something wrong or dangerous (or you made a policy mistake), you can quickly change your policy to the correct configuration, and the software would still function normally.
显式角色权限控制:更好的办法
就像上面已经说明的部分,使用隐式角色权限控制会使得代码更难以更改。如果你的代码在运行时候就可以更改权限并且也不影响用户的使用那就更棒了。这对于安全也是更加好的,因为如果你发现一些程序上的错误和危险,你可以很快的改变你的权限控制以改正配置,程序在这时候还能保持普通的运行。
So how can we enable these benefits? We can do this by being explicit as to what can actually be done in an application. But what does that mean exactly?
When you look at the implicit access control checks above, what were they really trying to do? What was the most fundamental control being performed?
所以我们怎么样才能保证这些好处呢?我们可以使用显式权限控制来完成这些的功能?但是这意味着什么呢?
当我们看到上面的隐式权限控制,我们到底是在试图去做什么呢?
到底什么是最基础的控制提供呢?
Fundamentally, those checks are trying to protect resources (project reports) as well as what actions a user could do to those resources (e.g. view/read them). When you break it down to this most primitive level, you can start to describe security policies in a much more fine-grained (and change-resilient) manner.
从根本上来说,这些检查是在试图保护资源(项目报告)或者说什么动作一个用户可以做的对于这些资源(例如:看/读这些)。当你把事情的分解到更加原理的部分,你可以开始去描述安全条款在于更加细粒度和更加复原改变的方向。
For example, let’s change the above code blocks to effectively do the same thing with resource-based semantics:
举例说明,我们把下面的代码用更加资源基础的语句来说明:
//Listing 3. Example Explicit Access Control security check: if (user.isPermitted("projectReport:view:12345")) { //show the project report button } else { //don't show the button }
This example is much more explicit as to what access is being controlled. The colon-delimited syntax isn’t really important here – it is just an example. More importantly, we are basically checking “If the current user is permitted to ‘view’ the ‘projectReport’ with ID ‘12345’, show the project report button”. That is, we’re explicitly attributing a concrete behavioral statement about a specific resource instance with a user account.
这个例子更加显式的说明了访问控制的方式。 冒号分隔的语法在这里并不是非常的重要,他只是一个语法的例子。更加重要的是,我们非常基础的编写了:“如果这个user是容许“view”这个项目报告的用ID 12345,展示项目报告的按钮。这个例子说明,我们明确的将一个行为动作和一个用户的账号声明并且关联了在一起
How is this better?
This latest example above has a subtle yet very important distinction: the code is now based on whatis being protected, not who might have an ability. Although apparently simple (and perhaps more obvious) conceptually, this has a major impact on development and production deployment practices:
如何做的更好?
最新的这个例子表明了一个事实:代码是基于被保护的这部分资源,而不是使用这些资源的那个角色。这在逻辑上只有微妙的不同,但是在整个部署和实现上造成了整个的差别和区别。
- Reduced Code Refactoring: By basing code on what the application can do, we’re basing our security on things that are core to the application itself and which change much less frequently – the resources that the application interacts with. Using this approach, software developers can modify security checks as they work on the application’s functionality – not the other way around as implicit RBAC so often requires.
- 降低代码重构:基础代码所能到达的程度,我们尽我们所写的是代码的核心部分并且使他很少发生改变-这些程序用来交互的资源。使用这个方法,程序员可以经常检查他们的安全模块,而不是像其他隐式RBAC这种需要重构整个代码部分。
- Resources and Actions are intuitive: Representing what is being protected and how it might be acted upon is a more natural way of thinking about the problem. The Object Oriented programming paradigm and REST communication models fundamentally reflect this viewpoint and are very successful because of it.
资源和行为是直观的:更直观更自然的思考和编写对于问题的解决是非常好的。面向对象编程和REST接口模式都是这种观点的现实表现。 - Flexible Security Model: The above code example does not dictate how a user, group, or role is permitted to perform an action on a resource. This means any security model design can be supported. For example, maybe behaviors (permissions) can be assigned directly to a user. Or perhaps they can be assigned to a role, which is in turn assigned to a user. Perhaps there is the notion of groups which have associations with roles, etc. The possibilities are open and can be customized based on your application.
- 灵活的安全模式:上面的代码示例不指定用户、组或角色如何在资源上执行动作。这意味着可以支持任何安全模型设计。例如,可以将行为(权限)直接分配给用户。或者,它们可以被分配给角色,而角色又被分配给用户。或者也可能又一个组拥有一种权限,等等。
- 你可以在你的应用程序上自由定制你自己的权限控制
- Externalized Security Policy Management: Because the source code only reflects resources and behaviors and not combinations of users, groups, and roles, that kind of assocation management can be externalized to a different part of code or to a dedicated tool or administrative console. This means developers don’t need to spend their time making security policy changes, and instead a business analyst or even end-user can make security policy changes as necessary.、
- 外部化安全策略管理:因为源代码只反映资源和行为,而不是用户、组和角色的组合,所以这种类型的关联管理可以被外部化到代码的不同部分或专用工具或管理控制台。这意味着开发人员不需要花费时间来进行安全策略更改,相反,业务分析师甚至最终用户可以根据需要更改安全策略。
- Make Changes at Runtime: Because security code checks do not depend on knowing how behaviors are associated (i.e. how groups, roles and users might be related), you can change those associations in an application’s security policy while the application is running. There is no need to refactor code to enforce a new security policy change, as is always the case under implicit RBAC.
- 在运行时进行更改:因为安全代码检查不依赖于知道行为是如何关联的(即,组、角色和用户可能如何关联),所以可以在应用程序运行时更改应用程序的安全策略中的那些关联。不需要重构代码来强制执行新的安全策略更改,就像隐式RBAC中的情况一样。