一个站点上面最基本都会有三种用户角色,未登录用户、已登录用户和管理员。这一次我们就来看看在revel框架下如何进行权限控制。

因为revel是MVC结构的,每一个url其实都会映射到一个具体的Controller.Action上面,所以权限控制落到实处就是对Action的访问进行控制。

那么思路是如下:

1. 有一个方法能够判定当前是什么角色。

2. 有一地方定义了每一个Action的访问权限要求。

3. 有一个方法能够在调用所有Action之前被调用,而且能够判定是否还要继续调用Action。

我们一项一项来解决。

存储当前用户的角色信息

先定义一个角色类型如下。

type Role int

const (
  AnonymousRole Role = iota
  UserRole
  AdminRole
)

定义个常量,用于在session里面存放当前用户的角色类型。

const (
  CSessionRole = "CSessionRole"
)

然后在处理用户登陆的方法中在session里保存角色信息。

func (c *Account) HandleLogin(email, password string) revel.Result {
  //在这里处理登陆逻辑

c.Session[CSessionRole] = UserRole

//在这里处理跳转和页面渲染
}

func (c *Account) HandleAdminLogin(account, password string) revel.Result {
  //在这里处理登陆逻辑

c.Session[CSessionRole] = AdminRole

//在这里处理跳转和页面渲染
}

我们现在可以从session中读取CSessionRole的值来判定当前用户是什么角色了。

定义Action的访问权限

在Controller层定义一个map,用于存放action的权限信息,如下。

func initAuthMap() {
  authMap = make(map[string]Role)
  authMap["account.login"] = AnonymousRole
  authMap["account.logout"] = UserRole
  authMap["admin.index"] = AdminRole
}

要注意的是initAuthMap需要在Controller包的init函数中调用,以进行权限控制初始化。

检查访问权限

revel框架提供的InterceptFunc(拦截方法)能够将一个方法注入到所有Action的调用之前或之后,这就给权限控制留出了空间。

让我们先定义一个方法用于检查权限。

func checkAuthentication(c *revel.Controller) revel.Result {
  //获取当前登陆用户的角色信息
  userRole, isExists := c.Session[util.CSessionRole]
  if !isExists {
    userRole = AnonymousRole
  }

//获取紧接着要调用的Action的名称
  action := strings.ToLower(c.Action)
  //获取相关action的权限定义
  if requiredRole, isExists = authMap[action]; isExists {
    //判断权限,如果权限要求不相符
    if requiredRole != userRole {
      //跳转到首页
      return c.Redirect((*Application).Index)
    }
  }

//返回nil表示可以接着调用后面的Action,在这里就代表有权限访问
  return nil
}

将这个InterceptFunc注册到revel的处理链中。

revel.InterceptFunc(checkAuthentication, revel.BEFORE, revel.ALL_CONTROLLERS)

好了,一个简单的权限控制系统做好了。这里只是展现了最基本的概念和构建的思路,掌握了之后,就算面对再复杂的要求也可以通过扩展其中的一个部分去满足。

另外,在我们的项目山坡网里,由于authMap定义了超过50个Action,很多时候一旦Action名字更改了就可能导致权限控制失效,针对这个问题,可以通过下面方法来解决。

authMap之前是用string做key,改成用reflect.Type就好了,注册的时候这么写。

authMap[reflect.TypeOf((*Account.HandleLogin)(nil)] = AnonymousRole

这样就可以用编译器帮助检查错误。

最后还得提一句,目前山坡网的Go代码已经超过两万行,且运行良好。revel是个好框架,值得信赖。

Go语言实战 - revel框架教程之权限控制的更多相关文章

  1. revel框架教程之权限控制

    Go语言实战 - revel框架教程之权限控制 一个站点上面最基本都会有三种用户角色,未登录用户.已登录用户和管理员.这一次我们就来看看在revel框架下如何进行权限控制. 因为revel是MVC结构 ...

  2. Go语言实战 - revel框架教程之用户注册

    用户注册.登录和注销是任何一个网站都必然会有的功能,可以说,这是重新造轮子做多的领域,每个做网站的人应该都做过很多遍.见微知著,从这么一个小功能其实就可以看到所使用的web框架中的大部分东西. 今天就 ...

  3. Go语言实战 - revel框架教程之缓存和Job

    所有的网站应该都会有一个非常简单的需求,首页一秒之内打开. 满足的方式主要有两种: 页面静态化,效果最好,对服务器基本没负担,只要带宽足够就好了.我知道一个PV过亿的站点就是全站静态(以前新浪也是), ...

  4. Go语言实战 - revel框架教程之MongDB的最佳搭档revmgo

    由于revel框架本身对于model层的编写没有提供任何指导,所以在设计这部分的时候就有些犹豫,反复斟酌到底怎样才算是最佳实践. 我在做山坡网的时候刚开始也纠结了一下,拿不准mongodb的sessi ...

  5. Go语言实战 - revel框架教程之CSRF(跨站请求伪造)保护

    CSRF是什么?请看这篇博文“浅谈CSRF攻击方式”,说的非常清楚. 现在做网站敢不防CSRF的我猜只有两种情况,一是没什么人访问,二是局域网应用.山坡网之前属于第一种情况,哈哈,所以至今没什么问题. ...

  6. revel框架教程之缓存和Job

    Go语言实战 - revel框架教程之缓存和Job   所有的网站应该都会有一个非常简单的需求,首页一秒之内打开. 满足的方式主要有两种: 页面静态化,效果最好,对服务器基本没负担,只要带宽足够就好了 ...

  7. shiro框架的四中权限控制方式

    https://www.cnblogs.com/cocosili/p/7103025.html 一.在自定义的realm中进行权限控制 在applicationContext.xml文件中添加  /a ...

  8. Yii 框架的Rbac [权限控制]

    转载自 xmlife 的博客 : http://blog.csdn.net/xmlife/article/details/50733451 1.首先我们要在配置文件的组件(component)里面配置 ...

  9. shiro框架学习-7- Shiro权限控制注解和编程方式

    讲解权限角色控制 @RequiresRoles, @RequiresPermissions等注解的使用和编程式控制 配置文件的方式 使用ShiroConfig 注解方式 @RequiresRoles( ...

随机推荐

  1. SqlLite 基本操作

    1.数据类型 ●  SQLite将数据划分为以下⼏几种存储类型: ●  integer : 整型值 ●  real : 浮点值 ●  text : ⽂文本字符串 ●  blob : ⼆二进制数据(⽐比 ...

  2. Hbuilder快捷键

    Hbuilder编辑器功能挺强大,体积相对来说比较小,下面是一些常用到的快捷键,尽快熟练使用,成为不用鼠标的大神!哈哈哈!!! alt+↓ 跳转到下一个可编辑区: ctrl+enter 向下换行: c ...

  3. python 爬虫(四)

    爬遍整个网络 1 当我们访问整个网络的时候,我们不可避免的会访问不同的网站,但是不同的网站会有完全不同的结构和内容... 现在一步一步的构建访问整个网络的脚本 I 从一个网站开始,每一次都爬向不同的网 ...

  4. Java 程序员必须掌握的 Linux 命令(转:导师Jencks)

    1.查找文件 find / -name filename.txt根据名称查找/目录下的filename.txt文件. find . -name "*.xml"递归查找所有的xml文 ...

  5. 关于ADO.NET连接ORACLE,使用ODAC连接中的一些问题

    ADO.NET连接ORACLE时,用到ODAC组件时,有几点注意的. 1.安装的具体方法见:http://jingyan.baidu.com/article/e4511cf336ce872b845ea ...

  6. what do i get for?

    有时候经常反思,做事究竟为了什么? 有时候,又无法解释,过去做的一些事情,是为了什么? 就像上小学时候明明挺到讨厌学习的,但上了初中后就开始玩命学习了 上高中时候认为自己真的是喜欢上学习了,上大学尼玛 ...

  7. 【生活没有希望】poj1273网络流大水题

    你不能把数据规模改大点吗= =我优化都不加都过了 #include <cstdio> #define INF 2147483647 int n,m,ans,x,y,z,M; ],l[],f ...

  8. 微信——获取用户基本信息及openid 、access_token、code

    获取用户信息,需要获取 access_token.openid 然后调用接口https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCES ...

  9. Java|今天起,别再扯订阅和回调函数

    编程史上有两个令人匪夷所思的说辞,一个是订阅,一个是回调函数. 我想应该还有很多同学为“事件的订阅”和“回调函数”所困扰,因为事情本来就不应该按这个套路来解释. 多直白,所谓的“回调函数”你完全可以线 ...

  10. 一张图系列——从CreateProcess到main函数的过程

    整体过程如下: 需要说明两点: 1.在XP中,新进程主线程的启动,会先执行一个用户态的APC,会执行ntdll!LdrInitializeThunk进行程序执行前的一些列初始化操作.其中很重要任务就是 ...