gocap

package module
v1.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 29, 2025 License: Apache-2.0 Imports: 15 Imported by: 0

README

Overview

go-cap@cap.js/server 的 Go 语言实现版

Notice
此包内部依赖 github.com/redis/go-redis/v9, 若使用 Redis 需要 v6.2.0 以上版本

Reference
Cap 源仓库
cap_go_server 另一个 Go 实现

Quick Start

项目内引用

go get github.com/ackcoder/go-cap

业务逻辑中使用

// 注: 创建实例一般放在 service 或 logic 层中
c := gocap.New()

challenge, err := c.CreateChallenge(context.Background())
fmt.Println("测试", challenge, err) //challenge: 待返回给前端组件的质询数据

HTTP 服务示例

package main

import (
	"net/http"
	"fmt"

	gocap "github.com/ackcoder/go-cap"
)

func main() {
	c := gocap.New()

	http.HandleFunc("/challenge", c.HandleCreateChallenge())
	http.HandleFunc("/redeem", c.HandleRedeemChallenge())
	http.HandleFunc("/validate", c.HandleValidateToken())

    fmt.Println("go-cap server start...")
    http.ListenAndServe(":8099", nil)
}

Usage

实例创建 gocap.New() 可选配置项入参:

WithStorage(storage Storage)
配置自定义存储, 默认是内存存储(sync.Map实现)
目前内置了 Redis 存储实现, 只需 Redis v6.2.0 以上版本
也可以自行实现 Storage 接口

WithChallenge(count, size, difficulty int)
配置质询数量(default:50)、大小(default:32)、难度(default:4)

WithChallengeExpires(expires int)
配置质询过期时间, 默认10分钟

WithTokenExpires(expires int)
配置验证令牌过期时间, 默认20分钟

WithTokenVerifyOnce(isOnce bool)
配置验证令牌检查次数, 默认一次性, 比较完即删除

WithLimiterParams(rps, burst int)
配置限流器参数, 默认10次/秒、最大突发50次
仅在 Handlexxx 方法调用时生效, 每个 Handlexxx 方法独立计算限流

License

参考源项目使用 Appache License 2.0, 请参阅 LICENSE 文件

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidChallenge  = errors.New("invalid challenge body")        //非法质询参数
	ErrChallengeExpired  = errors.New("challenge expired")             //质询令牌过期
	ErrInvalidSolutions  = errors.New("invalid solutions")             //非法解方案组参数
	ErrGenerateFailed    = errors.New("generate random string failed") //生成随机串失败
	ErrStorageNotDefined = errors.New("storage not defined")           //未定义存储实例
)

Functions

This section is empty.

Types

type Cap

type Cap struct {
	// contains filtered or unexported fields
}

func New

func New(opts ...CapOption) *Cap

func (*Cap) CreateChallenge

func (c *Cap) CreateChallenge(ctx context.Context) (*ChallengeData, error)

CreateChallenge 创建质询数据

func (*Cap) HandleCreateChallenge added in v1.1.0

func (c *Cap) HandleCreateChallenge() http.HandlerFunc

HandleCreateChallenge 创建质询 Http Handle 封装

func (*Cap) HandleRedeemChallenge added in v1.1.0

func (c *Cap) HandleRedeemChallenge() http.HandlerFunc

HandleRedeemChallenge 工作量证明兑换验证令牌 Http Handle 封装

func (*Cap) HandleValidateToken added in v1.1.0

func (c *Cap) HandleValidateToken() http.HandlerFunc

HandleValidateToken 检查验证令牌 Http Handle 封装

func (*Cap) RedeemChallenge

func (c *Cap) RedeemChallenge(ctx context.Context, token string, solutions []int64) (*TokenData, error)

RedeemChallenge 用工作量证明兑换验证令牌

  • {token} 质询令牌, 即 ChallengeData.Token
  • {solutions} 工作量证明/解方案组

func (*Cap) ValidateToken

func (c *Cap) ValidateToken(ctx context.Context, token string) bool

ValidateToken 检查验证令牌

  • {token} 验证令牌, 即 TokenData.Token

type CapOption

type CapOption func(c *Cap)

func WithChallenge

func WithChallenge(count, size, difficulty int) CapOption

配置质询数量/大小/难度

  • {count} 生成组数量. 默认50
  • {size} 每组大小. 默认32
  • {difficulty} 难度级别. 默认4

func WithChallengeExpires

func WithChallengeExpires(expires int) CapOption

配置质询(令牌)过期时间

  • {expires} 过期时间/秒. 默认600秒(10分钟)

func WithLimiterParams added in v1.1.0

func WithLimiterParams(rps, burst int) CapOption

配置限流器参数 (调用 Handlexxx 方法时生效)

  • {rps} 每秒通过数. 默认10次/秒. 都置为0时关闭限流
  • {burst} 最大突发容量. 默认50次. 都置为0时关闭限流

func WithStorage

func WithStorage(storage Storage) CapOption

配置自定义存储

func WithTokenExpires

func WithTokenExpires(expires int) CapOption

配置验证令牌过期时间

  • {expires} 过期时间/秒. 默认1200秒(20分钟)

func WithTokenVerifyOnce

func WithTokenVerifyOnce(isOnce bool) CapOption

配置验证令牌检查参数

  • {isOnce} 是否一次性验证. 默认true

type ChallengeData

type ChallengeData struct {
	Challenge ChallengeItem `json:"challenge"`
	Expires   int64         `json:"expires"` //过期时间,毫秒级时间戳
	Token     string        `json:"token"`   //质询令牌
}

质询数据内容

type ChallengeItem

type ChallengeItem struct {
	C int `json:"c"` //质询数量
	S int `json:"s"` //质询大小
	D int `json:"d"` //质询难度
}

type MemoryStorage

type MemoryStorage struct {
	// contains filtered or unexported fields
}

内存存储实现

创建实例 gocap.New() 时的默认存储 默认每隔 5分钟 清理一次过期数据

func NewMemoryStorage

func NewMemoryStorage(cleanup ...int64) *MemoryStorage

创建内存存储实例

  • {cleanup} 自动清理过期数据的定时间隔, 单位秒, 默认5分钟

func (*MemoryStorage) Cleanup

func (ms *MemoryStorage) Cleanup() error

func (*MemoryStorage) GetChallenge

func (ms *MemoryStorage) GetChallenge(ctx context.Context, token string, isGetDel ...bool) (ts int64, exists bool)

func (*MemoryStorage) GetToken

func (ms *MemoryStorage) GetToken(ctx context.Context, key string, isGetDel ...bool) (ts int64, exists bool)

func (*MemoryStorage) SetChallenge

func (ms *MemoryStorage) SetChallenge(ctx context.Context, token string, expiresTs int64) error

func (*MemoryStorage) SetToken

func (ms *MemoryStorage) SetToken(ctx context.Context, key string, expiresTs int64) error

type RedisStorage

type RedisStorage struct {
	// contains filtered or unexported fields
}

Redis 存储实现

func NewRedisStorage

func NewRedisStorage(conf *RedisStorageConfig) (*RedisStorage, error)

创建 Redis 存储实例

  • {conf} 配置项

func (*RedisStorage) Cleanup

func (s *RedisStorage) Cleanup() error

func (*RedisStorage) GetChallenge

func (rs *RedisStorage) GetChallenge(ctx context.Context, token string, isGetDel ...bool) (ts int64, exists bool)

func (*RedisStorage) GetToken

func (rs *RedisStorage) GetToken(ctx context.Context, key string, isGetDel ...bool) (ts int64, exists bool)

func (*RedisStorage) SetChallenge

func (rs *RedisStorage) SetChallenge(ctx context.Context, token string, expiresTs int64) error

func (*RedisStorage) SetToken

func (rs *RedisStorage) SetToken(ctx context.Context, key string, expiresTs int64) error

type RedisStorageConfig

type RedisStorageConfig struct {
	RedisAddr string `json:"redis_addr"` //required. host:port
	RedisUser string `json:"redis_user"` //optional.
	RedisPass string `json:"redis_pass"` //optional.
	RedisDb   int    `json:"redis_db"`   //optional.

	PrefixChallenge string `json:"prefix_challenge"` //质询数据缓存前缀
	PrefixToken     string `json:"prefix_token"`     //验证令牌数据缓存前缀
}

type Storage

type Storage interface {
	// SetChallenge 设置质询令牌
	//   - {token} 质询令牌
	//   - {expiresTs} 过期时刻, 秒级时间戳
	SetChallenge(ctx context.Context, token string, expiresTs int64) error
	// GetChallenge 获取质询令牌过期时间
	//   - {token} 质询令牌
	//   - {isGetDel} 是否获取后删除. 可选
	GetChallenge(ctx context.Context, token string, isGetDel ...bool) (ts int64, exists bool)

	// SetToken 设置验证令牌
	//   - {key} 验证令牌Key
	//   - {expiresTs} 过期时刻, 秒级时间戳
	SetToken(ctx context.Context, key string, expiresTs int64) error
	// GetToken 获取验证令牌过期时间
	//   - {key} 验证令牌Key
	//   - {isGetDel} 是否获取后删除. 可选
	GetToken(ctx context.Context, key string, isGetDel ...bool) (ts int64, exists bool)

	// Cleanup 清理过期数据
	Cleanup() error
}

type TokenData

type TokenData struct {
	Expires int64  `json:"expires,omitzero"` //过期时间,毫秒级时间戳
	Token   string `json:"token,omitzero"`   //验证令牌
}

验证令牌内容

type VerificationParams added in v1.1.0

type VerificationParams struct {
	Token     string  `json:"token"`              //质询令牌
	Solutions []int64 `json:"solutions,omitzero"` //质询解方案组
}

前端组件传入的参数

注: 用于 RedeemChallenge() 或 ValidateToken()

type VerificationResult added in v1.1.0

type VerificationResult struct {
	*TokenData
	Success bool   `json:"success"`
	Message string `json:"message,omitzero"`
}

返回前端组件的结果

注: 来自 RedeemChallenge() 或 ValidateToken()

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL