0x00 问题描述

书接上回,由于游戏服务器的新需求,但是游戏内置引擎没有hmac和sha1加密库,并且考虑了性能问题。所以采用远程调用PHP的方式去生成一个七牛的授权凭证(Access Token)。最近刚好在看Go的web框架,挑了一个国内比较成熟的Go语言编写的web框架Beego,所以为了熟悉Beego的框架,我准备将之前的PHP脚本放到Beego里面,作为我第一个Beego程序。

0x01 问题分析

beego 是一个典型的 MVC 框架,其中路由和控制器是整个框架中的核心模块。首先从路由包分析,先打开路由包看看里面定义了一些什么

package routers

import (
    "quickstart/controllers"
    "github.com/astaxie/beego"
)

func init() {
    beego.Router("/", &controllers.MainController{})
}

路由包里面我们看到执行了路由注册 beego.Router, 这个函数的功能是映射 URL 到 controller,第一个参数是 URL (用户请求的地址),这里我们注册的是 /,也就是我们访问的不带任何参数的 URL,第二个参数是对应的 Controller,也就是我们即将把请求分发到那个控制器来执行相应的逻辑,我们可以执行类似的方式注册如下路由:

beego.Router("/api/qiniu/auth/?:key", &controllers.QiniuAuthController{})

上述代码注册了一个路由,这个路由将/api/qiniu/auth/?:key 分发到控制器QiniuAuthController{}来进行处理。Beego为了用户更加方便的路由设置,beego 参考了 sinatra 的路由实现,支持多种方式的路由,其中 ?:key 定义了一个变量名称为key,也就是说该URL后面跟的字符串就是我们要操作的变量。当客户端进行HTTP请求的时候,这个变量就会被传到相应的控制器中进行下一步处理。

接下来是控制器,前面了解了如何把用户的请求分发到控制器,同样还是从源码分析入手

package controllers

import (
        "github.com/astaxie/beego"
)

type MainController struct {
        beego.Controller
}

func (this *MainController) Get() {
        this.Data["Website"] = "beego.me"
        this.Data["Email"] = "astaxie@gmail.com"
        this.TplName = "index.tpl"
}

上面的代码显示首先声明了一个控制器 MainController,这个控制器里面内嵌了 beego.Controller,这就是 Go 的嵌入方式,也就是 MainController 自动拥有了所有 beego.Controller 的方法(包括HTTP.GET请求)。func (this *MainController) Get()用于处理主控制器GET请求,代码描述了当GET请求触发时,回传两个数据 Website 和 Email,并用模板文件index.tpl来生成html文件返回给用户。> https://beego.me/docs/quickstart/controller.md

那么明白控制器原理之后,我们就可以开始写我们自己的控制器了,以QiniuAuthController{}这个控制器举例,主要功能是将经URL安全的Base64编码的字符串生成七牛的授权凭证(Access Token)。改凭证由HMAC方式加密,加密算法为SHA1。那么我们首先要做的是提取URL中请求的字符串。我们在路由包里定义了一个变量key用于加密字符串的传参。这里用Beego的函数Ctx.Input.Param提取出来并传到加密函数ComputeHmacSha1进行加密。

SHA-1

SHA-1(英语:Secure Hash Algorithm 1,中文名:安全散列算法1)是一种密码散列函数,美国国家安全局设计,并由美国国家标准技术研究所NIST发布为联邦数据处理标准(FIPS)。SHA-1可以生成一个被称为消息摘要的160位(20字节)散列值,散列值通常的呈现形式为40个十六进制数。

HMACSHA1是从 SHA1 哈希函数构造的一种键控哈希算法, 此 HMAC 进程将密钥与消息数据混合,使用哈希函数对混合结果进行哈希计算,将所得哈希值与该密钥混合,然后再次应用哈希函数。 输出的哈希值长度与SHA-1一致

摘自维基百科
加密步骤参考:https://www.kawanoii.cn/Code/qiniu-sign-access-token-api.html

0x02 Golang代码

package controllers

import (
    "encoding/base64"
    "crypto/sha1"
    "crypto/hmac"
    "github.com/astaxie/beego"
)
const(
SecretKey = ""
AccessKey = ""

)
type QiniuAuthController struct{
    beego.Controller
}
func ComputeHmacSha1(query string, secret string) string {
    message, _ := base64.URLEncoding.DecodeString(query)
    key := []byte(secret)
    h := hmac.New(sha1.New, key)
    h.Write([]byte(message))
    return base64.URLEncoding.EncodeToString(h.Sum(nil))
}
func (this *QiniuAuthController) Get(){
    this.Ctx.WriteString(AccessKey + ":" + ComputeHmacSha1(this.Ctx.Input.Param(":key"), SecretKey))
}

标签: Golang, Beego

评论已关闭