Golang中AKSK认证的实现

Golang中AKSK认证的实现,第1张

Golang实现AK/SK认证 一、AK/SK概述1. 什么是AKSK2. AK/SK认证过程 二、AK/SK认证例子1. 设计ak/sk的请求参数2. 数据库中保存sk3. 客户端生成签名4. 服务端校验签名

一、AK/SK概述 1. 什么是AKSK

ak/sk是一种身份认证方式,常用于系统间接口调用时的身份验证,其中ak为Access Key ID,sk为Secret Access Key。客户端和服务端两者会协商保存一份相同的sk,其中sk必须保密。

2. AK/SK认证过程

客户端在调用的服务端接口时候,会带上ak以及signature(使用sk对内容进行加密后得出的签名)进行请求,在服务端接收到这个请求的时候,首先会根据ak去数据库里面去找到对应的sk,然后使用sk对请求内容进行加密得到一个签名,然后对比客户端传过来的签名和服务端计算的出来的签名是否一致,如果一致则代表身份认证通过,反之则不通过。

二、AK/SK认证例子 1. 设计ak/sk的请求参数 platform_type:标明请求方是谁,即该例子中的aktime:请求时间,时间戳,将会被对应的sk配合加密算法进行加密,得到一个signature签名sign:签名,使用sk配合对应的加密算法后进行加密得到的签名。

当发送请求时,我们会带上这几个参数去请求接口,如请求https:///xxx.com/students?platform_type=school&time=1640494526&sign=54acba6857b284a8a481ed5913edd34d994721cc584305ff02c81bb3ced17212

2. 数据库中保存sk

一般来说,我们的sk生成是采用随机生成的方式,生成一个长度为64的随机字符串即可。
在数据库中我们可以生成这样的一个表

CREATE TABLE `app_permission`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `access key` varchar(50) NOT NULL,
  `secret_key` varchar(64) NOT NULL,
  `status` int(11) NOT NULL DEFAULT 1,
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`) USING BTREE
)

在表中插入对应的一条数据

INSERT INTO app_permission ( `access key`, `secret_key`)
VALUES
	( 'school', '7QFxrZ4aDA1mR5J96LwPoiO8HUgnefCvq2SMlz0IEtYsuyjbpNXcGW3TBkKVdhch');
3. 客户端生成签名
package main

import (
	"crypto"
	"crypto/hmac"
	_ "crypto/sha256"
	"encoding/hex"
	"errors"
	"strconv"
	"time"

	"github.com/beego/beego/v2/core/logs"
)

const (
	defaultHash = crypto.SHA256
)

func main() {
    //此处省略了从数据库读取sk的步骤
	secret := "7QFxrZ4aDA1mR5J96LwPoiO8HUgnefCvq2SMlz0IEtYsuyjbpNXcGW3TBkKVdhch"
	now := time.Now().Unix()
	timestamp := strconv.FormatInt(now, 10)

	//生成签名
	sign, err := GenerateSignature(timestamp, secret)
	if err != nil {
		logs.Warn("generate sign failed: %s", err.Error())
		return
	}
	
	logs.Debug("time: %s", timestamp)
	logs.Debug("sign: %s", sign)
}

//GenerateSignature 传入加密的内容和secret进行签名
func GenerateSignature(content, secret string) (string, error) {
	//判断设置的默认签名算法是否可用
	if !defaultHash.Available() {
		return "", errors.New("the requested hash function is unavailable")
	}

    //设置加密算法以及secret
	hasher := hmac.New(defaultHash.New, []byte(secret))
	//写入加密内容
	hasher.Write([]byte(content))

    //生成签名
	return hex.EncodeToString(hasher.Sum(nil)), nil
}
4. 服务端校验签名
package main

import (
	"crypto"
	"crypto/hmac"
	_ "crypto/sha256"
	"encoding/hex"
	"errors"

	"github.com/beego/beego/v2/core/logs"
)

const (
	defaultHash = crypto.SHA256
)

func main() {
	//此处省略了从数据库读取sk的步骤
	secret := "7QFxrZ4aDA1mR5J96LwPoiO8HUgnefCvq2SMlz0IEtYsuyjbpNXcGW3TBkKVdhch"
	timestamp := "1640494526"
	sign := "54acba6857b284a8a481ed5913edd34d994721cc584305ff02c81bb3ced17212"

	//服务端验证签名
	if err := VerifySignature(timestamp, sign, secret); err != nil {
		logs.Warn("verify signature failed, err: %s", err)
		return
	}
	logs.Debug("verify signature success")
}

//VerifySignature 校验签名
func VerifySignature(content, sign, secret string) error {
	//解码
	sig, err := hex.DecodeString(sign)
	if err != nil {
		return err
	}

	//判断加密算法是否可用
	if !defaultHash.Available() {
		return errors.New("the requested hash function is unavailable")
	}

	//设置secret
	hasher := hmac.New(defaultHash.New, []byte(secret))
	//写入加密内容
	hasher.Write([]byte(content))

	//判断签名是否一致
	if !hmac.Equal(sig, hasher.Sum(nil)) {
		return errors.New("signature is invalid")
	}

	return nil
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/990192.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存