跳转至主要内容

什么是 ABAC? Attribute-Based Access Control with Examples

What is ABAC?​

Attribute-based access control (ABAC) grants or denies a request by evaluating attributes against rules, instead of looking up who the user is or which role they hold. NIST, which published the reference definition in SP 800-162, groups the inputs into four kinds:

Attributes ofExamples
The subject (user or service)department, clearance level, employment type, age
The object (resource)owner, department, classification, status
The actionread, edit, approve, delete
The environmenttime of day, IP address or network, device, location

A rule is a condition over these attributes, for example "a user may read a document if they are in the same department as the document, during business hours". Because the rule refers to attributes rather than to named users or roles, new users and new documents are covered without adding any rule.

Casbin keeps ABAC simple: you pass structs or objects into Enforce() and reference their fields in the matcher. Complete applications are in the ABAC tutorials for Go, Node.js with Express, and Python with Flask.

ABAC vs RBAC​

RBAC decides on the user's roles: "editors may edit documents". ABAC decides on attributes: "the owner may edit the document". Roles are easy to audit, because you can list what a role allows and who holds it; attributes express rules about specific records and context, such as ownership, department or time, which roles alone cannot express without creating one role per record. Most applications combine them: roles decide which features a user can reach, and attribute conditions narrow that down to the records they may touch. Choosing an access control model compares ACL, RBAC, ABAC and ReBAC on one example and shows how to combine RBAC with ABAC in a single Casbin model.

Strengths and weaknesses​

  • Good at: ownership ("only their own"), context (business hours, office network), and data that carries its own labels (department, region, sensitivity). One rule can replace many role grants.
  • Weak at: auditing. "Who can read this document?" has no direct answer; you have to evaluate the rule against every user. Rules also need the attributes at hand, so the application usually loads the record before the check.

最小示例:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == r.obj.Owner

所以 r.obj 必须是一个带 Owner 字段的对象;Casbin 通过反射读取它。在 Go 中可以这样定义:

type testResource struct {
Name string
Owner string
}

也可以传入 JSON 字符串;启用 JSON 处理后,Casbin 会解析它们:

e, _ := NewEnforcer("examples/abac_model.conf")
e.EnableAcceptJsonRequest(true)

data1Json := `{ "Name": "data1", "Owner": "bob"}`

ok, err := e.Enforce("alice", data1Json, "read")
if err != nil {
// Handle JSON parsing errors
fmt.Printf("Enforcement failed: %v\n", err)
return
}

启用后,任何以 { 或 [ 开头的参数都会被当作 JSON 解析。无效的 JSON 会给出明确的错误;其他字符串保持原样。

// Valid JSON - automatically parsed
validJSON := `{"Name": "alice", "Age": 25}`
ok, err := e.Enforce(validJSON, "data1", "read") // Works correctly

// Invalid JSON - returns descriptive error
invalidJSON := `{"Name": "alice",}` // Trailing comma is invalid in JSON
ok, err := e.Enforce(invalidJSON, "data1", "read")
// Returns: "failed to parse JSON parameter at index 0: ..."

// Plain string - no parsing attempted
plainString := "alice"
ok, err := e.Enforce(plainString, "data1", "read") // Treated as plain string
备注

启用 JSON 参数支持会带来大约 1.1 到 1.5 倍的性能开销。

Environment attributes​

The request can carry more than sub, obj and act. Add a field for the environment and pass it to Enforce() like any other object. This model lets the owner edit their document at any time, and lets people from the same department read it between 9:00 and 18:00:

[request_definition]
r = sub, obj, act, env

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub.Name == r.obj.Owner || (r.act == "read" && r.sub.Department == r.obj.Department && r.env.Hour >= 9 && r.env.Hour < 18)
type User struct{ Name, Department string }
type Doc struct{ Name, Owner, Department string }
type Env struct{ Hour int }

doc := Doc{Name: "design.md", Owner: "alice", Department: "design"}
bob := User{Name: "bob", Department: "design"}

ok, _ := e.Enforce(bob, doc, "read", Env{Hour: 10}) // true
ok, _ = e.Enforce(bob, doc, "read", Env{Hour: 22}) // false: outside business hours
ok, _ = e.Enforce(bob, doc, "edit", Env{Hour: 10}) // false: bob is not the owner

使用 ABAC​

  1. 在匹配器中引用属性(例如 r.sub.Role、r.obj.Owner)。
  2. 把结构体或类的实例(或 JSON)传给 Enforce()。
警告

ABAC 的属性访问只适用于请求元素(r.sub、r.obj、r.act)。 p.sub 这类策略元素不能使用 ABAC,因为策略中无法存储结构体或类的定义。

提示

匹配器可以同时引用多个属性。示例:m = r.sub.Domain == r.obj.Domain。

提示

当策略中需要使用会与 CSV 解析冲突的逗号时,用引号把表达式括起来。示例:"keyMatch("bob", r.sub.Role)" 可以避免被错误拆分。

用 eval() 实现复杂规则​

对于更复杂的条件,把表达式放在 策略 中,用 eval() 求值,这样模型保持精简,策略保持灵活。

使用 eval() 的模型配置:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub_rule, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = eval(p.sub_rule) && r.obj == p.obj && r.act == p.act

p.sub_rule 是基于请求属性的表达式,在执行时求值。策略示例:

p, r.sub.Age > 18, /data1, read
p, r.sub.Age < 60, /data2, write

FAQ​

Is ABAC better than RBAC? Neither is better in general. ABAC expresses finer rules; RBAC is easier to review. Start with roles and add attribute conditions where roles stop fitting, such as ownership or time windows.

What is the difference between ABAC and PBAC? ABAC says what decisions are based on (attributes). PBAC says how the rules are managed: as policy data evaluated at run time. The eval() pattern above is both: attribute conditions stored as policy.

Is ABAC the same as XACML? No. XACML is an OASIS standard language for writing ABAC policies. Casbin does not use XACML; rules are written in the model's matcher or stored as policy rows.

Can I try ABAC without writing code? Yes. Pick an ABAC example in the online editor and edit the matcher and the request.

Comments are powered by giscus and GitHub Discussions. They load from giscus.app and GitHub only after you click the button below.