@darker
2015-12-15T14:29:07.000000Z
字数 6805
阅读 6268
CloudFoundry
从AccessToken中解析用户和客户端应用的附加信息并用这些信息决定是否具备访问权限是资源服务器的责任。本文将帮助资源服务器的开发者、客户端的维护者和用户账户理解可用信息范围和对访问权限的决策。UAA自身就是一个资源服务器(RS),因此我们就以UAA作为范例来诠释。
用户账户类型是"user"或者"admin"(取决于核心模式中的SCIM type
字段)。这些转换成授予的权限,分别是 [uaa.user]
或者 [uaa.admin,uaa.user]
,用于在UAA上鉴权的判定依据(管理员也有普通用户的角色)。授予的权限对于资源服务器并不是直接可见的,但他们在Access Token中以范围(Scope)类型出现。
资源服务器可以选择使用这些作为访问权限判定的依据的一部分,这些信息对于简单情形下的鉴权已经非常足够了(比如用户属于相对比较固定的一些角色中的一小部分),但一般情况下,他们需要维护他们自己的访问权限判定数据,因为在UAA上的角色并不必须与资源服务器上的完全一致。
对SCIM 用户组的支持目前只能通过用户对象的授权属性来提供。作为SCIM 客户端的资源服务器可以修改这些属性,但如果不要修改这些数据来让他们有管理员用户权限或许更好更安全。在任何时候,都推荐资源服务器给没有分配角色的新用户分配适当的默认权限。
有2个不同的场景:
vcap
环境: 集成测试或者生成中。如果带有一个默认活动的Spring特性的UAA服务不会生成用户数据库。一旦带有正确权限的客户端被注册,SCIM 端点可以用来提供用户账户。在这两种情况下用户账户和客户端注册通过在uaa.yml
文件中提供一些数据来在程序启动时一起初始化。
范例用户:
scim:
users:
- paul|wombat|paul@test.org|Paul|Smith|uaa.admin
- stefan|wallaby|stefan@test.org|Stefan|Schmidt
用户格式是:
username|password|email|first_name|last_name(|comma-separated-authorities)
.
记住授予的权限将作为用户组在SCIM中出现。
在他的默认配置中,当一个用户反复认证失败UAA并不会永久锁定账户。相反他会在之前一小时内登录5次失败后会临时锁定用户一段时间(默认是5分钟)。当一个用户成功授权后失败的次数就会被重置为0。
客户端应用程序元数据被资源服务器用于访问权限判定,并且被授权服务器(UAA自己)用于决定是否授予一个Access Token。
范围(Scope)是一个任意的字符串,但在一个客户端和资源服务器只有联系,因此当UAA作为一个资源服务器时,有一些 "标准"的值(scim.read
, scim.write
, passsword.write
, openid
等)。授权服务器使用的这些来拒绝那些不在上述列表中的请求, 而如果一个Token没有足够的范围(Scope)信息,资源服务器也会拒绝该请求对资源的访问。
UAA客户端应用程序有如下一些元数据(这些是可选的,但为了防止出错,有这些默认值更好):
client_credentials
, password
, implicit
, refresh_token
, authorization_code
。如果不是上述类型,授权服务器会直接拒绝请求。client_credentials
)。同时也是当客户端发起授权请求时,如果没有指定特别的Scope,这些将作为Token中的默认Scope。uaa.admin
)。当Token的授权类型是client_credentials
这些权限是Token的默认Scope。none
),但会从收取的权限的Scope中动态创建资源列表。资源的ID是从Scope分解出来的(比如Scope是cloud_controller.read
, 那么资源ID就是cloud_controller
)。客户端注册可以通过增加数据到uaa.yml
来完成。UAA总是会注册一个admin
客户端。附加额外的客户端注册有两种典型场景:
用香草代码和非自定义的uaa.yml
进行演示和调试。带有无活动Spring特性的一个 UAA服务启动时会初始化一些客户端(used in samples to make the out-of-the box
experience for new users as convenient as possible)。更多的客户端和用户账户会被集成测试创建。
一个vcap
环境:集成测试或者在生产环境中。默认情况下如果没有Spring特性被是活动的,不会有任何客户端会被注册,但客户端注册可以配置在 uaa.yml
和一些知名情况下。
当系统启动时没有在后台启动的客户端将从配置中引导(比如一旦系统已经启动而修改改变但并不会影响到已经产生的客户端)。如果引导组件像这样配置的话,某些字段(比如安全码)是可以被重置的。
admin
客户端有下面一些属性(在classpath路径下面的uaa.yml
中的配置总是会被自定义的配置文件中的配置所覆盖):
id: admin
secret: adminsecret
authorized-grant-types: client_credentials
scope: none
authorities: uaa.admin,clients.read,clients.write,clients.secret
通过增加额外的客户端,admin客户端可以用于启动系统。特殊情况下,用户账户不可以被配置,除非客户端可以访问资源 scim
。
默认的Spring Profile会初始化3个客户端,除admin
之外。例如我们从github下载后在命令行直接启动用于演示:
cf:
id: cf
authorized-grant-types: implicit
scope: cloud_controller.read,cloud_controller.write,openid,password.write
authorities: uaa.none
resource-ids: none
app:
id: app
secret: appclientsecret
authorized-grant-types: password,authorization_code,refresh_token
scope: cloud_controller.read,cloud_controller.write,openid,password.write,tokens.read,tokens.write
authorities: uaa.none
resource-ids: none
在 dev_setup
中,这些客户端(除了 admin
)账户会被初始化:
cloud_controller:
authorized-grant-types: client_credentials
scope: none
authorities: scim.read,scim.write,password.write,tokens.read,tokens.write
id: cloud_controller
secret: ...
resource-ids: none
cf:
id: cf
authorized-grant-types: implicit
scope: cloud_controller.read,cloud_controller.write,openid,password.write
authorities: uaa.none
resource-ids: none
redirect-uri: http://uaa.cloudfoundry.com/redirect/cf
Cloud Controller 安全码是在安装期间生成的。相同的客户端也会在CF.com中初始化,但安全码不同。
额外的客户端可以添加到uaa.yml
后在启动时自动初始化,比如:
oauth:
clients:
cf:
authorized-grant-types: implicit
scope: cloud_controller.read,cloud_controller.write,password.write,openid
authorities: uaa.none
id: cf
resource-ids: none
redirect-uri: http://uaa.cloudfoundry.com/redirect/cf
当一个客户端应用程序请求一个新的Access Token时,他可以提供一些必要的范围(Scope)(空格隔开,比如: scope=openid cloud_controller.read
)。如果提供了,UAA会使用这些设置并且如果一旦给予授权,这些就是token中的范围(scope)信息了。
否则,如果没有明确的给予这个参数,会有一个默认值提供。
授权给普通用户(授权类型除了client_credentials
以外的其他所有)的Token从客户端注册信息中的scope
字段获取默认的范围(Scope)信息。不管是否存在默认值,请求的范围(scope)信息都会被验证:
[openid, cloud_controller.read, cloud_controller.write]
参数了的。注意由于通过用户授权的过滤,意味着一个客户端请求得到的Token的授权范围可能变小。比如请求是scope=dash.admin dash.user openid
,但得到的是 dash.user openid
。Token对于客户端应用程序是不透明的。
client_credentials
类型授权的Token的范围(Scope)跟客户端的authorities字段一样的。请求一个不被允许的资源时会返回400错误码并且有错误提示信息。一个客户端一般拥有跟他相同的范围集合。
所有OAuth受保护的资源都有一个ID。任何请求如果没有与之匹配的资源ID都会被拒绝。不被OAuth2保护的资源没有资源ID(比如他们可以通过简单的HTTP Basic来认证)。
资源 ID = tokens
. 规则:
uaa.admin
, 或者tokens.write
uaa.admin
, 或者tokens.read
uaa.admin
, 或者tokens.write
uaa.admin
, 或者tokens.read
资源 ID = clients
. 规则:
clients.write
clients.read
资源 ID 为 null (因此所有的客户端都可以修改他们的密码). Rule:
clients.secret
uaa.admin
或者客户端只可以修改自己的安全码uaa.admin
或者客户端提供老的安全码uaa.admin
客户端也必须提供老的安全码次啊可以修改他自己的安全码资源 ID = password
. 规则:
password.write
uaa.admin
uaa.admin
或者用户提供老密码资源 ID = scim
. 规则:
列举或者查询用户
scim.read
删除、增加用户账户
scim.write
更新存在的用户账户
scim.write
另外,通过客户端权限 scim.me
(比如authorization_code或者password类型授权的)获取到的一个用户Token可以读取、查询和更新特定用户账户的权限。
资源 ID = scim
. 规则:
/ids/Users
filter
参数必须提供userName
, origin
和 id
会被返回scim.userids
用于SSO (OpenID Connect lite). 资源 ID = openid
. 规则:
openid
资源 ID = scim
. 规则:
列举和查询用户组:
scim.read
删除和增加用户组:
scim.write
更新用户组名称或者增删组员:
scim.write
或者 groups.update
另外,拥有权限 scim.me
的用户Token提供了下面的能力:
列举和查询用户组
reader
的所有用户组更新用户组名称或者增删组员
writer
的用户组UAA使用HTTP Basic来认证这些资源,因此他们不是OAuth2保护的资源,为了简化安全数据,只有注册的客户端才可以使用。调用者必须有一个安全码(secret),因此 cf
和其他简化模式的客户端是不需要的。
获取Access Token: /oauth/token
authorization_code
类型的客户端必须有一个安全码验证Access Token: /check_token
uaa.resource
获取Token Key (用于解码本地的 JWT token) : /token_key
uaa.resource
节点 /varz
是需要 HTTP Basic授权才可以访问的,认证信息在 uaa.yml
中进行配置。他们有默认值(varz:varzclientsecret
),但也可以通过系统属性覆盖掉。
登录节点是不安全的。任何客户端都可以访问他并且他也会返回关于系统和登录提示要求授权的一些信息给请求方。