Go语言实战 revel框架教程之权限控制

一个站点上面最基本都会有三种用户角色,未登录用户、已登录用户和管理员。这一次我们就来看看在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) HandleLoginemail, password string) revel.Result {
  //在这里处理登陆逻辑

  c.Session[CSessionRole] = UserRole

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

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

  c.Session[CSessionRole] = AdminRole

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

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

定义Action的访问权限

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

func initAuthMap) {
  authMap = makemap[string]Role)
  authMap[“account.login”] = AnonymousRole
  authMap[“account.logout”] = UserRole
  authMap[“admin.index”] = AdminRole
}

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

检查访问权限

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

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

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

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

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

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

revel.InterceptFunccheckAuthentication, revel.BEFORE, revel.ALL_CONTROLLERS)

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

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

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

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

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

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

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注