beego基于ak和sk完成认证
客户端
1. 基于ak/sk和某个算法,计算请求内容对应的签名signature。
2. 发送包含ak和signature的请求到服务端。
package main
import (
"crypto/sha1"
"fmt"
"io/ioutil"
"net/http"
"time"
)
const (
AK = "myak"
SK = "mysk"
)
func Sign(ak, sk, body string) string {
expiration := 30
info := fmt.Sprintf("%s_%d_%d", ak, time.Now().Unix(), expiration)
signature := sha1.Sum([]byte(fmt.Sprintf("%s_%s", info, body)))
return fmt.Sprintf("%s_%s", info, signature)
}
func main() {
req, err := http.NewRequest("GET", "http://127.0.0.1:8080/v1/object/a", nil)
if err != nil {
panic(err)
}
query := req.URL.Query()
sign := Sign(AK, SK, "")
query.Set("sign", sign)
req.URL.RawQuery = query.Encode()
if err != nil {
panic(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(bodyBytes))
}
服务端
1. 基于请求中的ak/自己的sk和相同算法,计算请求内容对应的签名signature。
2. 比较请求中的signature和自己计算得到的signature,两者相同时认证通过,否则失败。
package routers
import (
"beego-test/controllers"
"crypto/sha1"
"fmt"
"strconv"
"strings"
"time"
"github.com/astaxie/beego"
beego_context "github.com/astaxie/beego/context"
)
const (
AK = "myak"
SK = "mysk"
)
func Sign(ak, sk, body string) string {
expiration := 30
info := fmt.Sprintf("%s_%d_%d", ak, time.Now().Unix(), expiration)
signature := sha1.Sum([]byte(fmt.Sprintf("%s_%s", info, body)))
return fmt.Sprintf("%s_%s", info, signature)
}
func SignWithTime(ak, sk, body, nowUnixTimeStr string) string {
expiration := 30
info := fmt.Sprintf("%s_%s_%d", ak, nowUnixTimeStr, expiration)
signature := sha1.Sum([]byte(fmt.Sprintf("%s_%s", info, body)))
return fmt.Sprintf("%s_%s", info, signature)
}
func init() {
ns := beego.NewNamespace("/v1",
beego.NSCond(func(ctx *beego_context.Context) bool {
req := ctx.Input.Context.Request
query := req.URL.Query()
reqSign := query.Get("sign")
if reqSign == "" {
return false
}
reqSigns := strings.Split(reqSign, "_")
if len(reqSigns) != 4 {
return false
}
if reqSigns[0] != AK {
return false
}
len := req.ContentLength
body := make([]byte, len)
req.Body.Read(body)
newSignResult := SignWithTime(AK, SK, string(body), reqSigns[1])
if reqSign != newSignResult {
return false
}
reqTime, err := strconv.ParseInt(reqSigns[1], 10, 64)
if err != nil {
return false
}
expiration, err := strconv.ParseInt(reqSigns[2], 10, 64)
if err != nil {
return false
}
reqExpireTime := reqTime + expiration
if time.Now().Unix() > reqExpireTime {
return false
}
return true
}),
beego.NSNamespace("/object",
beego.NSRouter("/a", &controllers.ObjectController{}, "get:Get"),
),
)
beego.AddNamespace(ns)
}
package controllers
import (
"github.com/astaxie/beego"
)
type ObjectController struct {
beego.Controller
}
func (o *ObjectController) Get() {
o.Data["json"] = map[string]string{"ObjectId": "a"}
o.ServeJSON()
}

签名过期时间是30s,是req的URL params key=sign对应的value,内容是ak_请求时间戳_30_哈希值。
浙公网安备 33010602011771号