package auth import ( "fmt" "fusenapi/utils/encryption_decryption" "net/url" "reflect" ) type OperateType string const ( OpTypeRegister OperateType = "1" //注册的操作类型 OpTypeResetToken OperateType = "2" //重置密码类型 ) type ConfirmationLink[T any] struct { // Secret []byte secretGCM *encryption_decryption.SecretGCM[T] defaultTokenKey string // 默认key 是 token defaultOpTypeKey string link *url.URL } func NewConfirmationLink[T any](key string, UrlStr string) *ConfirmationLink[T] { u, err := url.Parse(UrlStr) if err != nil { panic(err) } return &ConfirmationLink[T]{ secretGCM: encryption_decryption.NewSecretGCM[T](key), defaultTokenKey: "token", defaultOpTypeKey: "optype", link: u, } } // WithDefaultTokenKey 设置默认Token Key func (cl *ConfirmationLink[T]) WithDefaultTokenKey(tkey string) *ConfirmationLink[T] { cl.defaultTokenKey = tkey return cl } // WithDefaultOpTypeKey 设置默认OpType Key func (cl *ConfirmationLink[T]) WithDefaultOpTypeKey(opkey string) *ConfirmationLink[T] { cl.defaultTokenKey = opkey return cl } // Generate 序列化链接传入需求的obj func (cl *ConfirmationLink[T]) Generate(obj *T) (string, error) { vValue := reflect.ValueOf(obj).Elem() opType := vValue.FieldByName("OperateType") if !opType.IsValid() { return "", fmt.Errorf("传入结构体 必须继承 OperateType") } op := opType.Interface().(OperateType) token, err := cl.Encrypt(obj) if err != nil { return "", err } return cl.generateWithToken(token, op) } // generateWithToken 序列化url带token func (cl *ConfirmationLink[T]) generateWithToken(token string, optype OperateType) (string, error) { q := cl.link.Query() if q.Has(cl.defaultTokenKey) { q.Set(cl.defaultTokenKey, token) } else { q.Add(cl.defaultTokenKey, token) } if q.Has(cl.defaultOpTypeKey) { q.Set(cl.defaultOpTypeKey, string(optype)) } else { q.Add(cl.defaultOpTypeKey, string(optype)) } // 生成确认链接 cl.link.RawQuery = q.Encode() return cl.link.String(), nil } func (cl *ConfirmationLink[T]) Encrypt(obj *T) (string, error) { return cl.secretGCM.Encrypt(obj) } func (cl *ConfirmationLink[T]) Decrypt(ciphertext string) (*T, error) { return cl.secretGCM.Decrypt(ciphertext) }