golang实现ID类型哈希编解码安全传输插件库hide的使用

Golang实现ID类型哈希编解码安全传输插件库hide的使用

Hide是一个简单的Go语言包,提供了一种ID类型,可以在编解码时转换为哈希字符串。这样可以避免将技术性ID直接发送给客户端,在API层进行转换。

安装

go get github.com/emvi/hide/v2

使用示例

基本用法

考虑以下用户结构体:

type User struct {
    Id       int64  `json:"id"`
    Username string `json:"username"`
}

当将这个结构体编码为JSON时,ID会以数字形式显示:

{
    "id": 123,
    "username": "foobar"
}

这会将技术性用户ID暴露给客户端。通过使用hide.ID类型,可以得到更好的结果:

type User struct {
    Id       hide.ID `json:"id"`
    Username string  `json:"username"`
}

现在JSON输出会变成:

{
  "id": "beJarVNaQM",
  "username": "foobar"
}

完整示例

package main

import (
	"encoding/json"
	"fmt"
	"github.com/emvi/hide"
)

// 定义用户结构体
type User struct {
	Id       hide.ID `json:"id"`
	Username string  `json:"username"`
}

func main() {
	// 创建一个用户实例
	user := User{
		Id:       123, // 可以直接使用int64值赋值
		Username: "foobar",
	}

	// 编码为JSON
	jsonData, err := json.Marshal(user)
	if err != nil {
		panic(err)
	}
	fmt.Println("JSON编码结果:", string(jsonData))
	// 输出: {"id":"beJarVNaQM","username":"foobar"}

	// 解码JSON
	var decodedUser User
	err = json.Unmarshal(jsonData, &decodedUser)
	if err != nil {
		panic(err)
	}
	fmt.Println("解码后的ID:", decodedUser.Id)
	// 输出: 123 (原始ID值)

	// 类型转换示例
	// 从hide.ID转换为int64
	originalID := int64(user.Id)
	fmt.Println("转换为int64:", originalID)
	
	// 从int64转换为hide.ID
	var newID hide.ID = 456
	fmt.Println("新的hide.ID:", newID)
}

自定义哈希函数

Hide默认使用hashids作为哈希函数,但你可以实现自己的哈希函数:

package main

import (
	"github.com/emvi/hide"
)

// 自定义哈希实现
type MyHash struct{}

func (h *MyHash) Encode(id []int64) (string, error) {
	// 实现自定义编码逻辑
	return "custom_" + fmt.Sprint(id[0]), nil
}

func (h *MyHash) Decode(hash string) ([]int64, error) {
	// 实现自定义解码逻辑
	idStr := strings.TrimPrefix(hash, "custom_")
	id, err := strconv.ParseInt(idStr, 10, 64)
	return []int64{id}, err
}

func main() {
	// 设置自定义哈希函数
	hide.UseHash(&MyHash{})

	// 现在所有hide.ID操作都会使用你的自定义哈希函数
}

注意事项

  1. 值为0的ID在编码为JSON或存储到数据库时会转换为null
  2. hide.ID内部实际上是int64类型,可以安全地进行类型转换
  3. 该库主要用于保护API中的技术性ID不被直接暴露

通过使用hide库,你可以轻松地在API层实现ID的哈希转换,既保护了技术细节,又不影响内部逻辑处理。


更多关于golang实现ID类型哈希编解码安全传输插件库hide的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现ID类型哈希编解码安全传输插件库hide的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang实现ID类型哈希编解码安全传输插件库hide的使用

hide是一个用于安全传输ID类型的Golang库,它通过对ID进行哈希编解码来保护敏感ID不被直接暴露在API或URL中。下面我将详细介绍如何使用这个库。

安装

首先安装hide库:

go get github.com/emvi/hide

基本使用

1. 定义ID类型

package main

import (
	"fmt"
	"github.com/emvi/hide"
)

type UserID int64

func main() {
	// 设置全局盐值(在生产环境中应从安全配置中获取)
	hide.SetSalt([]byte("your-secret-salt"))
	
	// 原始ID
	originalID := UserID(12345)
	
	// 编码ID
	encoded := hide.ToString(originalID)
	fmt.Println("Encoded ID:", encoded)
	
	// 解码ID
	decoded, err := hide.FromString(encoded)
	if err != nil {
		panic(err)
	}
	fmt.Println("Decoded ID:", UserID(decoded))
}

2. 在Web应用中使用

package main

import (
	"encoding/json"
	"net/http"
	"github.com/emvi/hide"
)

type User struct {
	ID   hide.ID `json:"id"`
	Name string `json:"name"`
}

func main() {
	hide.SetSalt([]byte("your-secret-salt"))
	
	http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
		// 模拟从数据库获取用户
		user := User{
			ID:   hide.ID(12345), // 实际存储的ID
			Name: "John Doe",
		}
		
		// 自动将ID编码为哈希字符串
		json.NewEncoder(w).Encode(user)
	})
	
	http.HandleFunc("/user/", func(w http.ResponseWriter, r *http.Request) {
		// 从URL获取哈希ID
		hashID := r.URL.Path[len("/user/"):]
		
		// 解码为实际ID
		id, err := hide.FromString(hashID)
		if err != nil {
			http.Error(w, "Invalid ID", http.StatusBadRequest)
			return
		}
		
		// 使用解码后的ID查询数据库...
		_ = id
		
		w.Write([]byte("User found with ID: " + hide.ToString(id)))
	})
	
	http.ListenAndServe(":8080", nil)
}

3. 自定义类型集成

package main

import (
	"database/sql/driver"
	"encoding/json"
	"fmt"
	"github.com/emvi/hide"
)

// 自定义ID类型
type CustomID hide.ID

// 实现json.Marshaler接口
func (id CustomID) MarshalJSON() ([]byte, error) {
	return json.Marshal(hide.ToString(hide.ID(id)))
}

// 实现json.Unmarshaler接口
func (id *CustomID) UnmarshalJSON(b []byte) error {
	var s string
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	
	decoded, err := hide.FromString(s)
	if err != nil {
		return err
	}
	
	*id = CustomID(decoded)
	return nil
}

// 实现driver.Valuer接口(用于数据库存储)
func (id CustomID) Value() (driver.Value, error) {
	return int64(id), nil
}

// 实现sql.Scanner接口(用于数据库读取)
func (id *CustomID) Scan(value interface{}) error {
	switch v := value.(type) {
	case int64:
		*id = CustomID(v)
		return nil
	case nil:
		return nil
	default:
		return fmt.Errorf("unsupported type: %T", v)
	}
}

func main() {
	hide.SetSalt([]byte("your-secret-salt"))
	
	id := CustomID(12345)
	
	// JSON编码
	jsonData, _ := json.Marshal(struct {
		ID CustomID `json:"id"`
	}{id})
	fmt.Println("JSON:", string(jsonData))
	
	// JSON解码
	var decoded struct {
		ID CustomID `json:"id"`
	}
	_ = json.Unmarshal(jsonData, &decoded)
	fmt.Println("Decoded ID:", decoded.ID)
}

高级配置

1. 自定义哈希长度

hide.SetHashLength(10) // 默认是8

2. 使用自定义哈希函数

hide.SetHashFunc(func(id hide.ID, salt []byte) string {
	// 实现自定义哈希逻辑
	return customHashFunction(id, salt)
})

3. 验证哈希ID

isValid := hide.IsHash("aBcDeF12") // 检查字符串是否符合哈希格式

安全注意事项

  1. 盐值管理

    • 盐值应该足够复杂且保密
    • 生产环境中应从安全配置中获取,不要硬编码在代码中
    • 更改盐值会使之前生成的哈希ID失效
  2. 哈希强度

    • 默认使用SHA256哈希算法
    • 可以通过SetHashFunc使用更强的哈希算法
  3. ID范围

    • 支持的最大ID值为1<<53-1(JavaScript安全整数范围)
    • 超出此范围的ID可能导致精度丢失

hide库提供了一种简单有效的方式来保护你的ID不被直接暴露,特别适合REST API开发。通过哈希转换,客户端只能看到无意义的字符串,而服务器可以安全地将其转换回原始ID。

回到顶部