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) 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是個好框架,值得信賴。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM