改为 jwt
This commit is contained in:
parent
ed4725e179
commit
cd66d3823e
@ -1,13 +1,17 @@
|
||||
package email
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/samber/lo"
|
||||
"github.com/wneessen/go-mail"
|
||||
"github.com/xmdhs/authlib-skin/config"
|
||||
@ -76,29 +80,54 @@ func (e Email) SendEmail(ctx context.Context, to string, subject, body string) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e Email) SendVerifyCode(ctx context.Context, email string, interval int) error {
|
||||
var emailTemplate = lo.Must(template.New("email").Parse(`<p>{{ .msg }}</p><a href="{{.url}}">{{ .url }}</a>`))
|
||||
|
||||
func (e Email) SendVerifyUrl(ctx context.Context, email string, interval int, host string) error {
|
||||
sendKey := []byte("SendEmail" + email)
|
||||
sendB, err := e.cache.Get(sendKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("SendRegVerifyCode: %w", err)
|
||||
return fmt.Errorf("SendVerifyUrl: %w", err)
|
||||
}
|
||||
if sendB == nil {
|
||||
return fmt.Errorf("SendRegVerifyCode: %w", ErrSendLimit)
|
||||
if sendB != nil {
|
||||
return fmt.Errorf("SendVerifyUrl: %w", ErrSendLimit)
|
||||
}
|
||||
err = e.cache.Put(sendKey, []byte{1}, time.Now().Add(time.Second*time.Duration(interval)))
|
||||
if err != nil {
|
||||
return fmt.Errorf("SendRegVerifyCode: %w", err)
|
||||
return fmt.Errorf("SendVerifyUrl: %w", err)
|
||||
}
|
||||
|
||||
code := lo.RandomString(8, append(lo.NumbersCharset, lo.UpperCaseLettersCharset...))
|
||||
|
||||
err = e.cache.Put([]byte("VerifyCode"+email), []byte(code), time.Now().Add(5*time.Minute))
|
||||
code, err := newJwtToken(e.pri, email)
|
||||
if err != nil {
|
||||
return fmt.Errorf("SendRegVerifyCode: %w", err)
|
||||
return fmt.Errorf("SendVerifyUrl: %w", err)
|
||||
}
|
||||
err = e.SendEmail(ctx, email, "验证你的邮箱", fmt.Sprintf("验证码:%v,五分钟内有效", code))
|
||||
|
||||
u := url.URL{
|
||||
Host: host,
|
||||
Scheme: "http",
|
||||
Path: "/test?" + code,
|
||||
}
|
||||
|
||||
if e.config.WebBaseUrl != "" {
|
||||
webBase, err := url.Parse(e.config.WebBaseUrl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("SendVerifyUrl: %w", err)
|
||||
}
|
||||
u.Host = webBase.Host
|
||||
u.Scheme = webBase.Scheme
|
||||
}
|
||||
|
||||
body := bytes.NewBuffer(nil)
|
||||
err = emailTemplate.Execute(body, map[string]any{
|
||||
"msg": "点击下方链接验证你的邮箱,1 天内有效",
|
||||
"url": u.String(),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("SendRegVerifyCode: %w", err)
|
||||
return fmt.Errorf("SendVerifyUrl: %w", err)
|
||||
}
|
||||
|
||||
err = e.SendEmail(ctx, email, "验证你的邮箱", body.String())
|
||||
if err != nil {
|
||||
return fmt.Errorf("SendVerifyUrl: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -106,20 +135,33 @@ func (e Email) SendVerifyCode(ctx context.Context, email string, interval int) e
|
||||
var (
|
||||
ErrCodeNotValid = errors.New("验证码无效")
|
||||
ErrSendLimit = errors.New("邮件发送限制")
|
||||
ErrTokenInvalid = errors.New("token 无效")
|
||||
)
|
||||
|
||||
func (e Email) VerifyCode(email, code string) error {
|
||||
key := []byte("VerifyCode" + email)
|
||||
codeb, err := e.cache.Get(key)
|
||||
func (e Email) VerifyJwt(email, jwtStr string) error {
|
||||
token, err := jwt.ParseWithClaims(jwtStr, &jwt.RegisteredClaims{}, func(t *jwt.Token) (interface{}, error) {
|
||||
return e.pri.PublicKey, nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("VerifyCode: %w", err)
|
||||
return fmt.Errorf("VerifyJwt: %w", err)
|
||||
}
|
||||
if string(codeb) != code {
|
||||
err := e.cache.Del(key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("VerifyCode: %w", err)
|
||||
}
|
||||
return ErrCodeNotValid
|
||||
sub, _ := token.Claims.GetSubject()
|
||||
if !token.Valid || sub != email {
|
||||
return fmt.Errorf("VerifyJwt: %w", ErrTokenInvalid)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newJwtToken(jwtKey *rsa.PrivateKey, email string) (string, error) {
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(1 * 24 * time.Hour)),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
Subject: email,
|
||||
Issuer: "authlib-skin email verification",
|
||||
})
|
||||
jwts, err := token.SignedString(jwtKey)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("newJwtToken: %w", err)
|
||||
}
|
||||
return jwts, nil
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user