API签名算法,go后端生成签名和验证签名

IT全栈视野
• 阅读 536

这次主要的实践内容是 API接口签名设计,以下是一些关键的步骤: 给前端分配一个 secretKey ,

以下是对这段代码的解读及教程:

一、代码功能概述 这段代码定义了一个名为getDataTest的函数,其主要功能是生成特定参数的签名,然后使用这些参数发送请求,并在请求成功后打印响应结果。签名的生成过程包括对给定参数进行排序、拼接特定字符串并使用 MD5 算法进行哈希计算。

前端使用第三方的库

import crypto from 'crypto-js';

二、代码详细解读

const getDataTest = () => {
  const secretKey = 'helloWorld';
  const params = {
    v: '1.0',
    page: "1",
    pageSize: "10",
  };

  // 获取当前时间戳
  const timestamp = "1724383084118";

  // 对参数进行 key 排序
  const sortedParams = {};
  Object.keys(params)
    .sort()
    .forEach(key => {
      sortedParams[key] = params[key];
    });

  // 生成签名
  const signatureData = Object.keys(sortedParams)
    .map(key => `${key}${sortedParams[key]}`)
    .join('') + `secretKey${secretKey}timestamp${timestamp}`;
  // 使用 MD5 算法进行哈希计算
  const hashedString = crypto.MD5(signatureData).toString();

  // 发送请求,(可以自己封装Axios)
  getData({
    ...sortedParams,
    timestamp,
    sign: hashedString,
  }
  ).then((res) => {
    console.log(res);
  });

}

3.调整参数和密钥 根据实际需求,可以调整params对象中的参数值以及secretKey的值。同时,如果时间戳不是固定的,可以使用动态生成时间戳的方法替代硬编码的时间戳。

4.处理请求结果 根据实际业务需求,对请求成功后的响应结果进行进一步的处理。在代码中,目前只是简单地打印了响应结果,可以根据具体情况进行更复杂的操作。

请注意,代码中的时间戳和密钥等可能需要根据实际情况进行动态生成和管理,以确保安全性和有效性。同时,确保getData函数的正确性和稳定性,以便成功发送请求并处理响应。

5.后端部分,以下是对这段代码的解读及使用教程:

package main

import (
    "crypto/md5"
    "encoding/hex"
    "fmt"
    "sort"
    "strconv"
    "strings"
    "time"

    "github.com/gin-gonic/gin"
)

// generateSignature 根据给定参数和密钥生成签名
func generateSignature(params map[string]interface{}, secretKey string, timestamp int64) string {
    // 移除签名和时间戳参数
    delete(params, "sign")
    delete(params, "timestamp")

    // 获取参数的键列表并排序
    keys := make([]string, 0, len(params))
    for k := range params {
        keys = append(keys, k)
    }
    sort.Strings(keys)

    var signatureBuilder strings.Builder
    // 拼接参数键值和密钥、时间戳
    for _, key := range keys {
        signatureBuilder.WriteString(key)
        signatureBuilder.WriteString(params[key].(string))
    }
    signatureBuilder.WriteString("secretKey" + secretKey)
    signatureBuilder.WriteString("timestamp" + strconv.FormatInt(timestamp, 10))

    fmt.Printf("|generateSignature: %s\n", signatureBuilder.String())
    // 计算 MD5 哈希并返回十六进制编码的签名
    hash := md5.Sum([]byte(signatureBuilder.String()))
    return hex.EncodeToString(hash[:])
}

// ValidateSignature 封装签名验证逻辑
func ValidateSignature(c *gin.Context, secretKey string) bool {
    receivedParams := make(map[string]interface{})
    if err := c.Bind(&receivedParams); err != nil {
        c.JSON(400, gin.H{"error": "Invalid request"})
        return false
    }

    receivedTimestamp, err := strconv.ParseInt(receivedParams["timestamp"].(string), 10, 64)
    if err != nil {
        c.JSON(400, gin.H{"error": "Invalid timestamp"})
        return false
    }

    currentTime := time.Now().UnixNano() / int64(time.Millisecond)
    if currentTime-receivedTimestamp > 120000 { // 允许 2 分钟的时间差
        c.JSON(400, gin.H{"error": "Timestamp expired"})
        return false
    }

    receivedSignature := receivedParams["sign"]

    expectedSignature := generateSignature(receivedParams, secretKey, receivedTimestamp)
    fmt.Print(expectedSignature)
    // 验证签名是否一致
    if receivedSignature != expectedSignature {
        return false
    } else {
        return true
    }
}

func main() {
    r := gin.Default()
    r.GET("/order", func(c *gin.Context) {
        secretKey := "helloWorld"
        if !ValidateSignature(c, secretKey) {
            return
        }

        c.JSON(200, gin.H{"message": "Request is valid", "secretKey": secretKey})
    })
    r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

客户端在发送请求时,需要在请求参数中包含正确的时间戳和签名。签名可以按照以下步骤生成: 确定请求参数,不包括sign和timestamp参数。 对参数的键进行排序。 将排序后的键值对拼接起来,再拼接上密钥和时间戳。 使用 MD5 算法计算哈希值,并将其转换为十六进制编码作为签名。

请注意,在实际应用中,可以根据具体需求对时间戳的有效期、密钥的生成和管理等进行进一步的优化和调整,以提高安全性和稳定性。

点赞
收藏
评论区
推荐文章
开放API接口签名验证,让你的接口从此不再裸奔
接口安全问题请求身份是否合法?请求参数是否被篡改?请求是否唯一?AccessKey&SecretKey(开放平台)请求身份为开发者分配AccessKey(开发者标识,确保唯一)和SecretKey(用于接口加密,确保不易被穷举,生成算法不易被猜测)。防止篡改参数签名1.按照请求参数名的字母升序排列非空请求参数(包含AccessK
Easter79 Easter79
3年前
springMVC笔记系列(8)——RequestParam注解
前面的文章介绍过注解@PathVariable,它能够为Rest风格的URL用占位符的方式传递一个参数,但是这个参数并不是真正意义上的请求参数。请求参数怎么处理是本文的主要内容。SpringMVC通过分析处理方法的签名,将HTTP请求信息绑定到处理方法的相应人参中。SpringMVC对控制器处理方法签名的限制是很宽松的,几乎可以按喜欢的任
手把手教大家实现一个电子签名
前言Hi,大家好,我是麦洛,最近在项目中遇到一个需求,需要做个html版的电子签名。周末休息整理下思路,顺便分享出来。😀由于笔者水平有限,文章难免有不当之处,恳请读者不吝赐教并提出意见由于公众号没有留言功能,如何找到我?🙈文章尾部我放置了自己的视频号,大家可以给我留言✌什么是电子签名?来自:百度百科电子签名是指中以电子形式所含、所附用于识别签名人身
Wesley13 Wesley13
3年前
unity android V1签名
unity2018版本默认签名会进行V1V2签名。如果只想进行V1签名的话可以进行以下操作。1.调整为gradle打包2.publishingsettings里面选择customgradletemplate,3.在gradle配置里面加入下述代码  !(https://oscimg.oschina.net/oscnet/up
Stella981 Stella981
3年前
OpenSSL和Python实现RSA Key公钥加密私钥解密
基于非对称算法的RSAKey主要有两个用途,数字签名和验证(私钥签名,公钥验证),以及非对称加解密(公钥加密,私钥解密)。本文提供一个基于OpenSSL和Python进行非对称加解密的例子。1\.OpenSSL实现非对称加解密1.1生成私钥,并导出公钥生成2048bit的PEM格式的RSAKey:Key.pem$openssl
Stella981 Stella981
3年前
Linux CA
CA(CertificateAuthority)证书颁发机构主要负责证书的颁发、管理以及归档和吊销。证书内包含了拥有证书者的姓名、地址、电子邮件帐号、公钥、证书有效期、发放证书的CA、CA的数字签名等信息。证书主要有三大功能:加密、签名、身份验证。1.什么是CA认证?CA认证,即CA认证机构,为电子签名相关各方提供真实性、可靠性验证
Stella981 Stella981
3年前
Node.js 中使用 ECDSA 签名遇到的坑
文/Fenying最近有个朋友问我关于Node.js下使用ECDSA的问题,主要是使用Node.js的Crypto模块无法校验网络传输过来的签名结果。在踩坑无数后,终于搞清楚了原因。坑0x00:签名输出格式在排除了证书、消息不一致的可能之后,我开始对比使用Node.js签名的结果与网络传输过来的签
Stella981 Stella981
3年前
Android Studio support 26.0.0
AS下如何生成自定义的.jks签名文件,以及如何生成数字签名(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fsunbinkang%2Farticle%2Fdetails%2F74990292)
Wesley13 Wesley13
3年前
URL地址参数进行加密传输提高网站安全性
通过密钥对url上的参数进行签名,比如url上有三个参数,按一定顺序排列后用一个只有服务端知道的密钥签名放在<a href"http://www.xxx.com/?a1&b2&c3&sigxxxxxxxx"里,这样,如果用户改了里面参数的内容,比如把a1改成了a2,但不知道你的密钥,也无法模拟你的签名,后台通过接收到的参数列表,用密钥进行签名
融云IM即时通讯 融云IM即时通讯
2星期前
融云IM干货丨如何为App Key配置HTTPS证书?
为AppKey配置HTTPS证书主要涉及以下几个步骤:生成密钥对和自签名证书:使用openssl工具生成密钥对和自签名证书,这是配置HTTPS的基础。可以通过以下命令生成:opensslgenrsaoutmykey.pem2048opensslreqnew
IT全栈视野
IT全栈视野
Lv1
我的微信公众号:IT全栈视野 与你分享更多见闻知识。
文章
13
粉丝
2
获赞
2