概述
2019独角兽企业重金招聘Python工程师标准>>>
今天分享的是使用二进制权限控制。
我们在go开发中经常会遇到使用二进制进行权限控制的情况,只不过go已经帮我们封装好了,不需要我们再人为进行管理。 比如在调用os.OpenFile()打开文件的时候
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
// 在这里我们打开了一个只读的文件
onlyRead, _ := os.OpenFile("./hello.txt", os.O_RDONLY, os.ModePerm)
defer onlyRead.Close()
data, err := ioutil.ReadAll(onlyRead)
if err != nil {
fmt.Printf("Can't read to hello.txt :%v n ", err)
}
fmt.Printf("hello.txt :%s n", string(data))
// 因为我们打开的是一个只读的文件
// 在这里尝试写入文件,会抛出一个
panic: write ./hello.txt: bad file descriptor
_, err = onlyRead.Write([]byte("This is a demo!!!"))
if err != nil {
fmt.Printf("Can't write to hello.txt :%v n ", err)
} else {
fmt.Printf("Write to hello.txt
success ... n ")
}
// 接下来我们打开一个可读可写的文件
// 这里我们用到 | 或运算符
readWrite, _ := os.OpenFile("./hello1.txt", os.O_CREATE|os.O_RDWR, os.ModePerm)
data, err = ioutil.ReadAll(readWrite)
if err != nil {
fmt.Printf("Can't read to hello1.txt :%v n ", err)
}
fmt.Printf("hello1.txt :%s n", string(data))
_, err = readWrite.Write([]byte("This is a demo!!!"))
if err != nil {
fmt.Printf("Can't write to hello1.txt :%v n ", err)
} else {
fmt.Printf("Write to hello1.txt
success ... n ")
}
// 下面是程序运行结果:
// hello.txt :hello world!
// 可以看到第一次打开的hello.txt在写入文件的时候报错了
// Can't write to hello.txt :write ./hello.txt: bad file descriptor
// hello1.txt :Hello1 world!This is a demo!!!This is a demo!!!
// Write to hello1.txt
success ...
}
注意看我们第二次打开hello1.txt的时候, 我们使用了 | 这个或运算符
readWrite, _ := os.OpenFile("./hello1.txt", os.O_CREATE|os.O_RDWR, os.ModePerm)
下面我们通过示例介绍 | 位或 和 & 位与运算符
package main
import (
"fmt"
)
const (
// 游客
TOURIST = 1 << iota
// 会员 1
MEMBER
// 管理员
// 管理拥有所有的权限
MANAGER = TOURIST | MEMBER
)
func main() {
fmt.Printf("TOURIST:%b, MEMBER:%b, MANAGER:%b n", TOURIST, MEMBER, MANAGER)
// 上面权限转成二进制:
// TOURIST => 0001
// MEMBER => 0010
// MANAGER => 0011
tourist(TOURIST, "用户1")
// 输出:
// flag:1 & needFlag:11 = 1
// flag: 0001
// needFlag: 0011
// 与运算结果:0001
// 用户:用户1 验证成功,可以访问 tourist ()
tourist(MEMBER, "用户2")
// 输出:
// flag:10 & needFlag:11 = 10
// flag:
0010
// needFlag: 0011
// 与运算结果:0010
// 用户:用户2 验证成功,可以访问 tourist ()
member(TOURIST, "用户3")
// 输出:
// flag:1 & needFlag:10 = 0
// flag:
0001
// needFlag: 0010
// 与运算结果:0000
// 用户:用户3 ,无权访问 member
member(MEMBER, "用户4")
// 输出:
// flag:10 & needFlag:10 = 10
// flag:
0010
// needFlag: 0010
// 与运算结果:0010
// 用户:用户4, 验证成功,可以访问 member ()
member(MANAGER, "用户5")
// 输出:
// flag:11 & needFlag:10 = 10
// flag:
0011
// needFlag: 0010
// 与运算结果:0010
// 用户:用户5, 验证成功,可以访问 member ()
// 管理员有搬用所有的权限
}
// 游客权限
func tourist(flag int, name string) {
if !checkAuth(flag, TOURIST|MEMBER) {
fmt.Printf("用户:%s
无权访问 tourist n", name)
return
} else {
fmt.Printf("用户:%s 验证成功,可以访问 tourist () n", name)
}
}
// 会员
func member(flag int, name string) {
if !checkAuth(flag, MEMBER) {
fmt.Printf("用户:%s ,无权访问 member n", name)
return
} else {
fmt.Printf("用户:%s, 验证成功,可以访问 member () n", name)
}
}
func checkAuth(flag int, needFlag int) bool {
fmt.Printf("nflag:%b & needFlag:%b = %b n", flag, needFlag, flag&needFlag)
return flag&needFlag != 0
}
我们将上面的代码重新过一遍 首先声明权限常量,这里用到了位移运算符和go的iota技巧,
TOURIST: 1 << (iota=0) 刚刚开始的时候,iota的值为0,表示将1左移0位。因为不需要左移,所以TOURIST=0001
MEMBER: 1 << (iota=1) 接下来 iota 变量在遇到第二行的时候,自增累加变成1。表示将1左移1位,所以MEMBER=0010
MANAGER: TOURIST | MEMBER ,最后,将TOURIST和MEMBER进行或运算。我们知道或运算只要有一位为1就为1, 所以MANAGER=(0001 | 0010 ) = 0011
const (
// 游客
TOURIST = 1 << iota
// 会员 1
MEMBER
// 管理员
// 管理拥有所有的权限
MANAGER = TOURIST | MEMBER
)
接着声明一个tourist函数,表示只要普通游客的权限就可以访问
// 游客权限
func tourist(flag int, name string) {
// 因为只需要游客的权限,所以普通的会员肯定也有这个权限
// 这里将TOURIST|MEMBER进行或运算后,访问权限为0011
// 也就是说,只要找拥有其中任意一个权限的人都可以访问该方法
if !checkAuth(flag, TOURIST|MEMBER) {
fmt.Printf("用户:%s 无权访问 tourist n", name)
return
} else {
fmt.Printf("用户:%s 验证成功,可以访问 tourist () n", name)
}
}
// 会员
func member(flag int, name string) {
// 这里需要会员的权限才可以访问,普通的游客是不能访问的
if !checkAuth(flag, MEMBER) {
fmt.Printf("用户:%s ,无权访问 member n", name)
return
} else {
fmt.Printf("用户:%s, 验证成功,可以访问 member () n", name)
}
}
最后我们进行权限验证的最重要的一个函数,这里用到了&与运行符,与运算符和我们常用的 && 差不多,只有两个数为1才为1
func checkAuth(flag int, needFlag int) bool {
fmt.Printf("nflag:%b & needFlag:%b = %b n", flag, needFlag, flag&needFlag)
// 比如: flag的二进制值为 0001,表示只有游客的权限,需要访问member()方法,而 member() 方法需要0010的权限,
// 我们将用户拥有的0001权限和访问member()需要的0010权限进行与运算得到 0001 & 0010 = 0000
// 二进制 0000 转成10十进制等于0
// 最终返回false ,表示用户没有访问member()的权限
return flag&needFlag != 0
}
完毕。。。
欢迎加入 dogo 技术交流群:437274005 点击右侧按钮快捷加入
转载于:https://my.oschina.net/wuciyou/blog/811703
最后
以上就是友好心情为你收集整理的go实用小技能(三)-使用二进制进行权限控制的全部内容,希望文章能够帮你解决go实用小技能(三)-使用二进制进行权限控制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复