Golang如何实现请求签名验证

基于HMAC-SHA256实现API请求签名验证,客户端按参数名排序拼接待签名字符串,结合HTTP方法、路径、时间戳、nonce等生成签名;服务端通过中间件校验accessKey、时间窗口、nonce唯一性,并重新计算签名比对,确保请求合法性与防重放攻击。

golang如何实现请求签名验证

在使用 Golang 开发 API 接口时,为了保证请求的合法性和安全性,通常会引入请求签名验证机制。这种机制可以防止请求被篡改或重放攻击。下面介绍一种常见的实现方式:基于 HMAC-SHA256 算法的签名验证流程。

1. 签名的基本原理

客户端和服务器共享一个密钥(secretKey),每次请求时,客户端根据请求参数和时间戳生成签名,并将签名随请求发送。服务端收到请求后,使用相同的算法和密钥重新计算签名,并与客户端传来的签名比对。

核心要素包括:

请求参数:所有参与签名的参数需按规则排序 时间戳(timestamp):防止重放攻击 随机字符串(nonce):增加唯一性 API密钥(accessKey 和 secretKey):用于身份识别和签名计算 HTTP方法、路径、Body(如需要):确保请求完整性

2. 客户端生成签名

假设客户端要发送一个 POST 请求到 /api/v1/order,携带参数:

TextCortex TextCortex

AI写作能手,在几秒钟内创建内容。

TextCortex 62 查看详情 TextCortex

立即学习“go语言免费学习笔记(深入)”;

accessKey=abc123&timestamp=1712345678&nonce=randomxyz&amount=100&product=phone

步骤如下:

将所有参数按字段名字母升序排序 拼接成 query string 格式(不编码 key 和 value,或统一 URL 编码) 构造待签名字符串,例如:
POST&/api/v1/order&accessKey=abc123&amount=100&nonce=randomxyz&product=phone&timestamp=1712345678 使用 secretKey 对该字符串进行 HMAC-SHA256 计算,并转为十六进制小写字符串 将生成的 signature 添加到请求头或参数中发送示例代码(客户端):

package mainimport (    "crypto/hmac"    "crypto/sha256"    "encoding/hex"    "fmt"    "sort"    "strings")func generateSignature(httpMethod, uri, secretKey string, params map[string]string) string {    var keys []string    for k := range params {        keys = append(keys, k)    }    sort.Strings(keys)    var pairs []string    for _, k := range keys {        pairs = append(pairs, fmt.Sprintf("%s=%s", k, params[k]))    }    queryString := strings.Join(pairs, "&")    signStr := fmt.Sprintf("%s&%s&%s", httpMethod, uri, queryString)    h := hmac.New(sha256.New, []byte(secretKey))    h.Write([]byte(signStr))    return hex.EncodeToString(h.Sum(nil))}func main() {    params := map[string]string{        "accessKey": "abc123",        "timestamp": "1712345678",        "nonce":     "randomxyz",        "amount":    "100",        "product":   "phone",    }    sig := generateSignature("POST", "/api/v1/order", "my_secret_key_123", params)    fmt.Println("Signature:", sig)}

3. 服务端验证签名

服务端接收到请求后,执行类似步骤:

从请求中提取 accessKey,查询对应 secretKey 校验 timestamp 是否在允许的时间窗口内(如 ±5 分钟) 检查 nonce 是否已使用过(可缓存一段时间,防重放) 用相同规则拼接参数并生成签名 使用 hmac.Equal 安全比较签名是否一致Gin 框架中的中间件示例:

package mainimport (    "crypto/hmac"    "crypto/sha256"    "encoding/hex"    "net/http"    "sort"    "strings"    "time"    "github.com/gin-gonic/gin")var secretKeyMap = map[string]string{    "abc123": "my_secret_key_123",}func SignVerifyMiddleware() gin.HandlerFunc {    return func(c *gin.Context) {        accessKey := c.PostForm("accessKey")        timestampStr := c.PostForm("timestamp")        nonce := c.PostForm("nonce")        clientSig := c.GetHeader("X-Signature")        if accessKey == "" || timestampStr == "" || nonce == "" || clientSig == "" {            c.JSON(401, gin.H{"error": "missing required fields"})            c.Abort()            return        }        secretKey, exists := secretKeyMap[accessKey]        if !exists {            c.JSON(401, gin.H{"error": "invalid accessKey"})            c.Abort()            return        }        // 验证时间戳        timestamp, err := time.ParseUnix(timestampStr, 10)        if err != nil || time.Since(timestamp).Abs() > 5*time.Minute {            c.JSON(401, gin.H{"error": "timestamp invalid"})            c.Abort()            return        }        // TODO: 使用 Redis 或内存缓存检查 nonce 是否重复        // 收集所有 form 参数(可根据实际需求扩展支持 query、JSON 等)        params := make(map[string]string)        c.Request.ParseForm()        for k, v := range c.Request.PostForm {            if len(v) > 0 {                params[k] = v[0]            }        }        delete(params, "") // 清理空key        // 生成待签名字符串(同客户端)        var keys []string        for k := range params {            keys = append(keys, k)        }        sort.Strings(keys)        var pairs []string        for _, k := range keys {            pairs = append(pairs, fmt.Sprintf("%s=%s", k, params[k]))        }        queryString := strings.Join(pairs, "&")        signStr := fmt.Sprintf("%s&%s&%s", c.Request.Method, c.Request.URL.Path, queryString)        h := hmac.New(sha256.New, []byte(secretKey))        h.Write([]byte(signStr))        serverSig := hex.EncodeToString(h.Sum(nil))        // 安全比较        if !hmac.Equal([]byte(serverSig), []byte(clientSig)) {            c.JSON(401, gin.H{"error": "signature mismatch"})            c.Abort()            return        }        c.Next()    }}

4. 安全建议与注意事项

使用 HTTPS:防止密钥和签名在传输中泄露 限制 timestamp 有效期:通常设置为 ±5 分钟 使用唯一 nonce 并去重:可用 Redis 记录一段时间内的 nonce 敏感操作加动态 Token:如短信验证码、二次确认等 避免日志记录 secretKey 或完整签名字符串 参数编码一致性:客户端和服务端必须使用相同的编码规则基本上就这些。通过上述方式,可以在 Golang 项目中实现一套简单而有效的请求签名验证机制,提升接口安全性。

以上就是Golang如何实现请求签名验证的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1021671.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月2日 01:31:55
下一篇 2025年12月2日 01:32:16

相关推荐

  • AWS 概念指南

    要充分了解AWS,您不需要掌握每项服务。专注于涵盖云计算主要领域的核心服务集,因为这将为您的构建奠定坚实的基础。以下是需要重点关注的关键 AWS 服务和概念的细分,以便更好地理解: 核心计算服务 EC2(弹性计算云):了解如何启动、配置和管理虚拟机。 弹性负载均衡器 (ELB):了解负载均衡以及如何…

    2025年12月19日
    000
  • 如何使用 JavaScript 遍历 JSON 数组?

    在 javascript 中遍历 json 数组 在处理 json 数据时,遍历数组中的元素至关重要。本文将指导您使用 javascript 遍历 json 数组,从而访问和处理其中的数据。 在您的代码示例中,已通过 eval() 函数解析了 info.filelist 中的 json 字符串。要遍…

    2025年12月19日
    000
  • React 中的异步派生

    我们遇到了一个问题,异步很难。 假设您有一个简单的 get api,一个接收 searchtext 作为参数的搜索。您使用您偏好的 http 请求工具调用它并得到一个承诺,它解析为您正在搜索的任何内容的列表。 如何在 react 组件中调用它? 首先,需要注意一件事,我所描述的可以建模为: resu…

    2025年12月19日
    000
  • React 模块化简介:AMD 和 CommonJS 模块化

    模块化是现代应用程序开发的核心,尤其是在使用像 react 这样的库时。了解模块化和不同的模块化方法(例如 amd 和 commonjs)是开发高效、可维护和可扩展代码的关键。在这篇博文中,我们将探讨模块化在 react 应用程序中的工作原理、为什么它很重要,以及 amd 和 commonjs 的模…

    2025年12月19日
    000
  • 微信小程序中如何实现多个输入框的值相加?

    小程序实现输入框值相加 在微信小程序中,当您有多个输入框需要实现值相加功能时,可以使用以下方法: page({ data: { inputs: [{ value: ” }, { value: ” }, …], // 存放输入框值 result: 0 // 保存相加结果 }, bindinpu…

    2025年12月19日
    000
  • 您需要探索的有趣的新 Github 存储库

    如果您像我一样,总是在 GitHub 上寻找酷炫的新项目来深入研究,那么您将会大饱口福!我收集了五个目前正在掀起波澜的杰出存储库 – 无论您是喜欢聊天机器人构建器、下一代 CRM、文档解析还是可视化云架构,每个人都可以在这里找到一些东西。让我们一起探索吧! 1.六角机器人 Hexabot…

    2025年12月19日
    000
  • 我的第一个 JavaScript Web 应用程序:交互式图像坐标查找器

    在福赛大学完成我的第一门 javascript 课程后,我渴望投入到一个可以测试我的新技能的项目中。我的目标是创造一些功能性、直观且实用的东西。这导致了我的第一个 javascript web 应用程序的开发:交互式图像坐标查找器。 该应用程序允许用户上传地图图像,单击以记录坐标,并将其保存为具有唯…

    2025年12月19日
    000
  • 如何使用百度 Echarts 设置不同点颜色?

    百度 echarts不同点颜色设置 本文针对百度 echarts 点的不同颜色设置问题进行解答。 示例:(并非广告) [echarts 示例](http://echarts.baidu.com/examples/editor.html?c=effectscatter-bmap) 如图所示,如何实现不…

    2025年12月19日
    000
  • JS 表单非空验证后无法获取焦点,如何解决?

    js 表单非空验证后无法获取焦点 在进行 js 表单非空验证时,如果出现提交表单后,提示手机号为空但仍然通过的情况,可能是由于获取手机号码的值时存在问题。 解决方法: 检查代码是否正确获取到了手机号的值。可以使用 console.write 检查获取的值是否存在。确保非空验证代码在提交表单之前执行。…

    2025年12月19日
    000
  • 如何使用 ag-grid 轻松处理前端表格中的嵌套行?

    前端嵌套表格行处理利器 在处理前端表格时,嵌套行往往会带来挑战。本文将为大家推荐一款强大的工具:ag-grid。 ag-grid 的优势 ag-grid 是一款功能丰富的 javascript 数据表格库,专为处理复杂表格设计而打造。它提供了对嵌套行的原生支持,让你轻松创建和管理层次结构化的表格。 …

    2025年12月19日
    000
  • 使用生成式 AI 进行 MarkoJS 前端开发:现代方法

    在不断发展的 Web 开发中,MarkoJS 作为最强大的前端框架之一占据了中心舞台,提供了独特的功能,例如在编译时服务器端渲染 HTML 并大大简化了反应式组件。将此与生成式 AI 的新功能相结合,MarkoJS 巩固了其在满足开发人员创建现代、高效和动态 Web 应用程序方面的需求的地位。 在本…

    2025年12月19日
    000
  • Nodejs 中的日志记录和监控:最佳实践

    有效的日志记录和监控对于维护应用程序运行状况、快速识别问题和提高性能至关重要。在本文中,我们将深入探讨 node.js 应用程序的日志记录和监控,涵盖选择日志记录级别、设置结构化日志、与监控工具集成以及使用 winston 和 elasticsearch 的最佳实践等关键主题。 日志记录和监控简介 …

    2025年12月19日
    000
  • 如何使用 React 和 Rest API 构建网站(React 基础知识解释)

    react 和 typescript 是用于构建可扩展、可维护和安全网站的强大框架。 react 提供了灵活且基于组件的架构,而 typescript 在 javascript 中添加了静态类型,以实现干净且可读的代码。本文将指导您使用 react 和 typescript 设置一个简单的网站,涵盖…

    2025年12月19日 好文分享
    000
  • 微信小程序输入框如何实现值相加并实时显示?

    如何让微信小程序中输入框的值与下一个相加并显示 在微信小程序中,当用户在多个输入框中输入值时,需要保存这些值并根据要求进行计算,如将其相加。以下是如何实现这一目标: 第一步:在输入框上绑定 bindchange 事件。该事件会在输入框值发生变化时触发。 第二步:在 bindchange 事件处理函数…

    2025年12月19日
    000
  • 使用变更集管理您的版本控制和变更日志

    本文概述了变更集及其在 t3-env 中的用法。 什么是变更集? 这是变更集存储库自述文件中提供的官方定义。 变更集工作流程旨在帮助人们进行更改,一直到发布。它让贡献者声明如何发布他们的更改,然后我们自动更新包版本和更改日志,并根据提供的信息发布新版本的包。 changesets 专注于解决多包存储…

    2025年12月19日
    000
  • 使用 Zod 和 Faker 构建用于生成模拟数据的 TypeScript 助手

    构建应用程序时,模拟数据对于测试、开发和原型设计非常宝贵。借助 zod 强大的模式验证和 faker 的数据生成功能,我们可以创建一个强大的助手来为任何 zod 模式生成真实的、符合模式的模拟数据。 介绍 在本指南中,我们将创建一个辅助函数generatemockdatafromschema,它接受…

    2025年12月19日
    000
  • 如何使用无限查询(TanStack Query)进行无限滚动

    这是您的帖子翻译成英文: 在这篇文章中,我将教您如何使用 tanstack 查询(特别是无限查询)实现无限滚动。我们将使用 vite 创建照片源并设置无限滚动。首先,打开终端并运行以下命令来克隆具有基本配置的项目: git clone –branch start https://github.co…

    2025年12月19日
    000
  • 微信小程序中,如何实现多个输入框的值相加并显示?

    如何让小程序中的多个输入框值相加并显示 在微信小程序中,如有多个输入框用于收集用户输入,需要保留并累加这些输入值,并在页面上显示。 voici les étapes pour y parvenir : Page({ data: { values: [0, 0], // 输入值数组,初始值为 0 su…

    好文分享 2025年12月19日
    000
  • 开发者传奇 – 为 Z 世代解读

    有人说 10 倍开发者是真实的,也有人说这只是公司的骗局。但让我们面对现实吧:只有 sigma alpha omega 男性研磨集开发人员 拥有超越凡人编码的纯粹 gyatt。当您进行代码审查并且您的首席开发人员再次思考“哎哟,这里有披萨”时,您就知道您已经解锁了内心的 10 倍。 这些传奇人物就像…

    2025年12月19日
    000
  • bootstrap-datetimepicker 中 daysOfWeekDisabled 和 enabledDates 选项如何协同使用?

    bootstrap-datetimepicker 联合使用 daysofweekdisabled 和 enableddates 使用 eonasdan 开发的 bootstrap datetimepicker v4.17.45 时,遇到了 daysofweekdisabled 选项和 enabled…

    2025年12月19日
    000

发表回复

登录后才能评论
关注微信