go实用小技能(三)-使用二进制进行权限控制
2016-12-25 00:00
274 查看
今天分享的是使用二进制权限控制。
我们在go开发中经常会遇到使用二进制进行权限控制的情况,只不过go已经帮我们封装好了,不需要我们再人为进行管理。
比如在调用os.OpenFile()打开文件的时候
注意看我们第二次打开hello1.txt的时候, 我们使用了 | 这个或运算符
下面我们通过示例介绍 | 位或 和 & 位与运算符
我们将上面的代码重新过一遍
首先声明权限常量,这里用到了位移运算符和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
接着声明一个tourist函数,表示只要普通游客的权限就可以访问
最后我们进行权限验证的最重要的一个函数,这里用到了&与运行符,与运算符和我们常用的 && 差不多,只有两个数为1才为1
完毕。。。
欢迎加入 dogo 技术交流群:437274005 点击右侧按钮快捷加入
我们在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 点击右侧按钮快捷加入
相关文章推荐
- java编程中使用二进制进行权限或状态控制
- java编程中使用二进制进行权限或状态控制
- java中使用二进制进行权限控制
- java编程中使用二进制进行权限或状态控制
- zookeeper使用ACL进行权限控制C++
- 使用Struts 拦截namespace进行权限控制
- 使用Struts 拦截namespace进行权限控制
- js:读写二进制变通方法,需要有权限控制adodb.stream,可以配合hta使用
- 使用二进制位进行权限控制
- 使用CVSNT进行权限控制
- 使用Struts 拦截namespace进行权限控制
- 使用Zend_Auth和Zend_Acl进行登录认证及根据用户角色进行权限控制
- 使用Struts 拦截namespace进行权限控制
- 使用Struts2拦截器进行权限控制
- 使用Struts 拦截namespace进行权限控制
- ssh项目整合shiro时,在struts2的action中使用shiro的注解进行权限控制时,NoSuchMethodException:com.sun.proxy.$Proxy26
- 使用CVSNT进行权限控制
- 拦截器权限控制使用Struts 拦截namespace进行权限控制-java教程
- Mvc 3 使用Attribute进行权限控制
- 使用Zend_Auth和Zend_Acl进行登录认证及根据用户角色进行权限控制