1、介绍

Ladon 是一个 Go 语言库,用于实现访问控制策略(Access Control Policies),并提供灵活的权限验证功能。它通常用于基于角色(RBAC)、基于属性(ABAC)等方式的权限管理。Ladon 提供了一种方法来定义策略,并根据主体(subject)、资源(resource)和操作(action)对访问进行验证

1.1、主要特点

  1. 策略管理:Ladon 允许你定义策略来控制哪些用户或角色对哪些资源可以执行什么操作
  2. 支持多种存储后端:Ladon 支持不同类型的存储后端,如内存存储、数据库存储、文件存储等。你可以根据需求选择存储策略
  3. 灵活的匹配机制:Ladon 支持基于正则表达式的匹配,可以灵活地定义哪些资源、操作或主体符合策略
  4. 支持多种控制模型
  5. RBAC(基于角色的访问控制):通过角色来管理用户权限。
  6. ABAC(基于属性的访问控制):通过资源、操作等属性来控制访问

1.2、重要概念

  1. 策略(Policy)
    策略是 Ladon 中的核心概念,它定义了哪些主体(用户或角色)可以在特定的资源上执行什么操作。每个策略都包括以下元素:
  2. ID:策略的唯一标识符
  3. Description:策略的描述
  4. Subjects:策略适用的主体(通常是用户、角色等)
  5. Resources:策略作用的资源
  6. Actions:策略允许的操作
  7. Effect:策略的效果,可以是 AllowAccess 或 DenyAccess
  8. 策略存储(Store)
    策略存储是用来保存和检索策略的地方。Ladon 提供了接口,你可以实现自己的存储方法(如内存存储、数据库存储等),并将其与策略管理器连接
  9. 策略管理器(Manager)
    策略管理器负责创建、检索和验证策略。它将策略存储和策略检查结合在一起,通过与存储后端交互来管理策略
  10. 权限验证(IsAllowed)
    IsAllowed() 方法用于根据存储的策略验证某个主体(用户、角色)是否有权在某个资源上执行某个操作。它是权限控制的核心方法

2、安装

go get github.com/ory/ladon@v1.2.0

3、基本使用

package main

import (
    "fmt"
    "github.com/ory/ladon"
    "log"
)

// 定义一个策略存储类
type MemoryStore struct {
    policies map[string]*ladon.DefaultPolicy
}

// 创建一个内存存储
func NewMemoryStore() *MemoryStore {
    return &MemoryStore{
        policies: make(map[string]*ladon.DefaultPolicy),
    }
}

// 实现策略存储接口 : 创建策略
func (m *MemoryStore) Create(policy *ladon.DefaultPolicy) error {
    m.policies[policy.ID] = policy
    return nil
}

// 获取策略
func (m *MemoryStore) Get(id string) (*ladon.DefaultPolicy, error) {
    policy, exists := m.policies[id]
    if !exists {
        return nil, fmt.Errorf("policy not found")
    }
    return policy, nil
}

// 检查是否允许执行某个操作
func (m *MemoryStore) IsAllowed(subject, resource, action string) error {
    for _, policy := range m.policies {
        if contains(policy.Subjects, subject) &&
            contains(policy.Resources, resource) &&
            contains(policy.Actions, action) {
            if policy.Effect == ladon.AllowAccess {
                return nil
            }
        }
    }
    return fmt.Errorf("permission denied")
}

// 辅助函数 : 检查字符串是否存在于切片中
func contains(arr []string, str string) bool {
    for _, item := range arr {
        if item == str {
            return true
        }
    }
    return false
}

func main() {
    // 创建一个内存存储实例
    store := NewMemoryStore()

    // 定义一个策略
    policy := &ladon.DefaultPolicy{
        ID:          "1",
        Description: "Allow 'admin' to read 'resource_1'",
        Subjects:    []string{"admin"},
        Resources:   []string{"resource_1"},
        Actions:     []string{"read"},
        Effect:      ladon.AllowAccess, // 允许访问
    }

    // 将策略存储到内存中
    err := store.Create(policy)
    if err != nil {
        log.Fatalf("Failed to create policy : %s", err)
        return
    }

    // 检查 "admin" 是否有权限执行 "read" 操作
    err = store.IsAllowed("admin", "resource_1", "read")
    if err != nil {
        log.Printf("Access denied for admin : %s", err)
    } else {
        fmt.Println("Access granted to admin.")
    }

    // 检查 "guest" 是否有权限执行 "read" 操作
    err = store.IsAllowed("guest", "resource_1", "read")
    if err != nil {
        log.Printf("Access denied for guest : %s", err)
    } else {
        fmt.Println("Access granted to guest.")
    }
}

运行结果 :

Access granted to admin.
2024/12/21 23:51:20 Access denied for guest : permission denied

journey
32 声望22 粉丝