Thoughs on goRBAC

mikespook · · 786 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Code refactoring is not an easy job, but it has to be done in most of the times. I just completed the lightweight role based access control library: goRBAC’s refactoring. There are some feedbacks and questions about the design and usage. I think it would be better writing something to share some design ideas and practice principles which will make things easier.

rbac

The master branch of current goRBAC’s source code is intended to be Version 2. While the previous version has been tagged as Version 1 with the v1.dev branch on Github. And this article will only discuss Version 2 (the master branch).

The new design separates goRBAC into 3 parts: core, interfaces & implements, and helper functions.

The core is the major part of goRBAC and manages inheritance relationship of roles. It contains only one struct `RBAC` with 8 methods. It’s easy to understand and use. What you need is reading the document.

`Role` is the only interface directly communicating with `RBAC`. It has two methods: `Id` returns the identity of a role and `Permit` checks if the permission is permitted to a role. For example, you can implement a Role named `God` and has all permissions as the God.

type God struct {}

func(g *God) Id() string {
    return "God"
}

func(g *God) Permit(p Permission) bool {
    return true
}

For making things easier, goRBAC has a built-in role `StdRole` which can be used in a real-life application and also be a good example for anyone who want to write their own `Role` implementation. Moreover, when you implement your own `Role`, struct embedding can be your good friend.

Eg.,

type MyOwnRole struct {
    gorbac.StdRole
    // extra fields
}
// extra functions

One thing is worth to be noticed, some methods in `Role` like AssignPermission, RevokePermission, Permissions etc. has been removed from the interface. Despite those methods don’t have any affection with `Role` and `RBAC`, they originally defined as a standard API and designed for some data persistence task. I decided to remove them after I joined “Go 1.6 Global Release Party – Auckland Zone” with some great discussions. “Less is exponentially more” again!

Another important interface is `Permission` which is only communicating with `Role`. It also has two methods: `Id` and `Match`. `Id` is the identity of a permission. `Match` is used to detect if current permission matches another one.

The library also supplies two built-in structs for `Permission`.

First one is `StdPermission` which uses `Id` to detect if two permissions are matching.

Another one is `LayerPermission` which supports multi-layers matching and can be very useful to design something like access management of control panels. To be exact, permission “admin” matches “admin:article” and “admin:article:delete”; “admin:article” matches “admin:article:delete”, but you will get a negative result by reversing matching.

And when you have some “hard mode” access control, implementing your own `Permission` is a good idea.

Eg.,

type FuzzPermission struct {
    IdStr string
}

func(f *FuzzPermission) Id() string {
    return f.IdStr
}

func(f *FuzzPermission) Permit(p Permission) bool {
    if f.IdStr == p.Id() { // exactly matched
        return true
    }
    q, ok := p.(*FuzzPermission)
    if !ok { // Not same type
        return false
    }
    return strings.Contains(f.IdStr, p.Id())
}

Well, I’m not sure what circumstance will use this kind of permissions, but you can have it.


有疑问加站长微信联系(非本文作者)

本文来自:mikespook 的博客

感谢作者:mikespook

查看原文:Thoughs on goRBAC

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

786 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传