TODO: password

This commit is contained in:
eson 2023-09-04 01:40:28 +08:00
parent 31f46b64b5
commit 9c89f0fe4a
6 changed files with 97 additions and 27 deletions

View File

@ -92,14 +92,15 @@ func (l *UserEmailConfirmationLogic) UserEmailConfirmation(req *types.RequestEma
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
// userinfo 传入值时, 一定不为null
token, err := l.svcCtx.OAuthTokenManger.Decrypt(req.Token)
if err != nil {
logx.Error(err)
return resp.SetStatus(basic.CodeOAuthRegisterTokenErr)
}
switch token.OperateType {
switch auth.OperateType(req.OpType) {
case auth.OpTypeRegister:
token, err := l.svcCtx.OAuthTokenManger.Decrypt(req.Token)
if err != nil {
logx.Error(err)
return resp.SetStatus(basic.CodeOAuthRegisterTokenErr)
}
if time.Since(token.CreateAt) > 30*time.Minute {
return resp.SetStatusWithMessage(basic.CodeOAuthConfirmationTimeoutErr, "Verification links expire after 30 minute.")
}
@ -135,6 +136,36 @@ func (l *UserEmailConfirmationLogic) UserEmailConfirmation(req *types.RequestEma
}
logx.Info("success:", token.TraceId)
}
case auth.OpTypeResetToken:
rt, err := l.svcCtx.ResetTokenManger.Decrypt(req.Token) // ResetToken
if err != nil {
logx.Error(err)
return resp.SetStatus(basic.CodeOAuthResetTokenDecryptErr, err.Error())
}
// TODO: 存储
if rt.OperateType != auth.OpTypeResetToken {
return resp.SetStatus(basic.CodeOAuthTypeErr, "error OperateType: rt.OperateType != auth.OpTypeResetToken")
}
err = l.svcCtx.AllModels.FsUser.Transaction(l.ctx, func(tx *gorm.DB) error {
user := &gmodel.FsUser{Id: int64(rt.UserId)}
err := tx.Take(user).Error
if err != nil {
return err
}
if *user.PasswordHash != rt.OldPassword {
return fmt.Errorf("password had beed updated")
}
return tx.Update("PasswordHash", rt.NewPassword).Error
})
if err != nil {
return resp.SetStatus(basic.CodeDbSqlErr, err.Error())
}
return resp.SetStatus(basic.CodeOK)
default:
return resp.SetStatus(basic.CodeOAuthRegisterTokenErr)

View File

@ -48,7 +48,8 @@ type RequestGoogleLogin struct {
}
type RequestEmailConfirmation struct {
Token string `form:"token"` // 操作Token
Token string `form:"token"` // 操作Token
OpType string `form:"optype"` // 操作类型
}
type RequestEmailRegister struct {

View File

@ -102,7 +102,8 @@ type RequestGoogleLogin {
}
type RequestEmailConfirmation {
Token string `form:"token"` // 操作Token
Token string `form:"token"` // 操作Token
OpType string `form:"optype"` // 操作类型
}
type RequestEmailRegister {

View File

@ -1,23 +1,27 @@
package auth
import (
"fmt"
"fusenapi/utils/encryption_decryption"
"net/url"
"reflect"
)
type OperateType int8
type OperateType string
const (
OpTypeRegister OperateType = 1 //注册的操作类型
OpTypeResetToken OperateType = 2 //重置密码类型
OpTypeRegister OperateType = "1" //注册的操作类型
OpTypeResetToken OperateType = "2" //重置密码类型
)
type ConfirmationLink[T any] struct {
// Secret []byte
SecretGCM *encryption_decryption.SecretGCM[T]
secretGCM *encryption_decryption.SecretGCM[T]
DefaultQueryKey string // 默认key 是 token
link *url.URL
defaultTokenKey string // 默认key 是 token
defaultOpTypeKey string
link *url.URL
}
func NewConfirmationLink[T any](key string, UrlStr string) *ConfirmationLink[T] {
@ -27,31 +31,58 @@ func NewConfirmationLink[T any](key string, UrlStr string) *ConfirmationLink[T]
}
return &ConfirmationLink[T]{
SecretGCM: encryption_decryption.NewSecretGCM[T](key),
DefaultQueryKey: "token",
link: u,
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)
return cl.generateWithToken(token, op)
}
// GenerateWithToken 序列化url带token
func (cl *ConfirmationLink[T]) GenerateWithToken(token string) (string, error) {
// generateWithToken 序列化url带token
func (cl *ConfirmationLink[T]) generateWithToken(token string, optype OperateType) (string, error) {
q := cl.link.Query()
if q.Has(cl.DefaultQueryKey) {
q.Set(cl.DefaultQueryKey, token)
if q.Has(cl.defaultTokenKey) {
q.Set(cl.defaultTokenKey, token)
} else {
q.Add(cl.DefaultQueryKey, token)
q.Add(cl.defaultTokenKey, token)
}
if q.Has(cl.defaultOpTypeKey) {
q.Set(cl.defaultOpTypeKey, string(optype))
} else {
q.Add(cl.defaultOpTypeKey, string(optype))
}
// 生成确认链接
@ -61,9 +92,9 @@ func (cl *ConfirmationLink[T]) GenerateWithToken(token string) (string, error) {
}
func (cl *ConfirmationLink[T]) Encrypt(obj *T) (string, error) {
return cl.SecretGCM.Encrypt(obj)
return cl.secretGCM.Encrypt(obj)
}
func (cl *ConfirmationLink[T]) Decrypt(ciphertext string) (*T, error) {
return cl.SecretGCM.Decrypt(ciphertext)
return cl.secretGCM.Decrypt(ciphertext)
}

View File

@ -116,6 +116,7 @@ func BenchmarkAesXor(b *testing.B) {
func TestConfirmationLink(t *testing.T) {
type Register struct {
OperateType
Id int64
Password string
platform string
@ -125,12 +126,16 @@ func TestConfirmationLink(t *testing.T) {
key := "21321321"
cl := NewConfirmationLink[Register](key, "http://localhost:9900/api/auth/oauth2/register")
uri, _ := cl.Generate(&Register{Id: 39, Password: "21dsadsad", platform: "google", Expired: time.Now().UTC()})
robj := &Register{Id: 39, Password: "21dsadsad", platform: "google", Expired: time.Now().UTC(), OperateType: OpTypeResetToken}
uri, _ := cl.Generate(robj)
log.Println(uri)
u, _ := url.Parse(uri)
log.Println(uri)
token := u.Query()["token"]
log.Println(cl.Decrypt(token[0]))
}
const secret = "your-256-bit-secret"

View File

@ -42,6 +42,7 @@ type ResetToken struct {
UserId int64 // guest_id 需要继承
Wid string // websocket 通道id
Email string // email
NewPassword string // 新密码
OldPassword string // 旧密码
TraceId string //链路Id
CreateAt time.Time // 创建时间