From a10e100364feffda2e94d23f0a4635b36c6f98cd Mon Sep 17 00:00:00 2001
From: eson <9673575+githubcontent@user.noreply.gitee.com>
Date: Mon, 24 Jul 2023 17:22:06 +0800
Subject: [PATCH] save
---
server/auth/auth.go | 36 ++++
server/auth/etc/auth.yaml | 19 ++
server/auth/internal/config/config.go | 27 +++
.../internal/handler/acceptcookiehandler.go | 35 ++++
server/auth/internal/handler/routes.go | 37 ++++
.../handler/useremailregisterhandler.go | 6 +-
.../handler/usergoogleloginhandler.go | 6 +-
.../internal/handler/userloginhandler.go | 6 +-
.../auth/internal/logic/acceptcookielogic.go | 43 +++++
.../internal/logic/useremailregisterlogic.go | 7 +-
.../internal/logic/usergoogleloginlogic.go | 177 ++++++++++++++++++
server/auth/internal/logic/userloginlogic.go | 93 +++++++++
server/auth/internal/svc/servicecontext.go | 61 ++++++
server/auth/internal/types/types.go | 101 ++++++++++
server/home-user-auth/etc/home-user-auth.yaml | 10 -
.../home-user-auth/internal/handler/routes.go | 20 --
.../internal/logic/email_manager.go | 161 ++++++++++++++++
.../internal/logic/usergoogleloginlogic.go | 101 ++++++----
server/home-user-auth/internal/types/types.go | 18 --
server_api/auth.api | 53 ++++++
server_api/home-user-auth.api | 39 ----
utils/auth/user.go | 81 ++++++++
utils/basic/basic.go | 4 +-
23 files changed, 1004 insertions(+), 137 deletions(-)
create mode 100644 server/auth/auth.go
create mode 100644 server/auth/etc/auth.yaml
create mode 100644 server/auth/internal/config/config.go
create mode 100644 server/auth/internal/handler/acceptcookiehandler.go
create mode 100644 server/auth/internal/handler/routes.go
rename server/{home-user-auth => auth}/internal/handler/useremailregisterhandler.go (81%)
rename server/{home-user-auth => auth}/internal/handler/usergoogleloginhandler.go (81%)
rename server/{home-user-auth => auth}/internal/handler/userloginhandler.go (80%)
create mode 100644 server/auth/internal/logic/acceptcookielogic.go
rename server/{home-user-auth => auth}/internal/logic/useremailregisterlogic.go (84%)
create mode 100644 server/auth/internal/logic/usergoogleloginlogic.go
create mode 100644 server/auth/internal/logic/userloginlogic.go
create mode 100644 server/auth/internal/svc/servicecontext.go
create mode 100644 server/auth/internal/types/types.go
create mode 100644 server/home-user-auth/internal/logic/email_manager.go
create mode 100644 server_api/auth.api
diff --git a/server/auth/auth.go b/server/auth/auth.go
new file mode 100644
index 00000000..f1f3eca9
--- /dev/null
+++ b/server/auth/auth.go
@@ -0,0 +1,36 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "net/http"
+ "time"
+
+ "fusenapi/utils/auth"
+
+ "fusenapi/server/auth/internal/config"
+ "fusenapi/server/auth/internal/handler"
+ "fusenapi/server/auth/internal/svc"
+
+ "github.com/zeromicro/go-zero/core/conf"
+ "github.com/zeromicro/go-zero/rest"
+)
+
+var configFile = flag.String("f", "etc/auth.yaml", "the config file")
+
+func main() {
+ flag.Parse()
+
+ var c config.Config
+ conf.MustLoad(*configFile, &c)
+ c.Timeout = int64(time.Second * 15)
+ server := rest.MustNewServer(c.RestConf, rest.WithCustomCors(auth.FsCors, func(w http.ResponseWriter) {
+ }))
+ defer server.Stop()
+
+ ctx := svc.NewServiceContext(c)
+ handler.RegisterHandlers(server, ctx)
+
+ fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
+ server.Start()
+}
diff --git a/server/auth/etc/auth.yaml b/server/auth/etc/auth.yaml
new file mode 100644
index 00000000..fac66390
--- /dev/null
+++ b/server/auth/etc/auth.yaml
@@ -0,0 +1,19 @@
+Name: auth
+Host: 0.0.0.0
+Port: 9980
+MainAddress: "http://localhost:9900"
+SourceMysql: fusentest:XErSYmLELKMnf3Dh@tcp(110.41.19.98:3306)/fusentest
+Auth:
+ AccessSecret: fusen2023
+ AccessExpire: 2592000
+ RefreshAfter: 1592000
+
+
+OAuth:
+ google:
+ appid: "1064842923358-e94msq2glj6qr4lrva9ts3hqjjt53q8h.apps.googleusercontent.com"
+ secret: "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"
+
+ facebook:
+ appid: "1095953604597065"
+ secret: "b146872550a190d5275b1420c212002e"
\ No newline at end of file
diff --git a/server/auth/internal/config/config.go b/server/auth/internal/config/config.go
new file mode 100644
index 00000000..679c8627
--- /dev/null
+++ b/server/auth/internal/config/config.go
@@ -0,0 +1,27 @@
+package config
+
+import (
+ "fusenapi/server/auth/internal/types"
+
+ "github.com/zeromicro/go-zero/rest"
+)
+
+type Config struct {
+ rest.RestConf
+ SourceMysql string
+ Auth types.Auth
+
+ MainAddress string
+
+ OAuth struct {
+ Google struct {
+ Appid string
+ Secret string
+ }
+
+ Facebook struct {
+ Appid string
+ Secret string
+ }
+ }
+}
diff --git a/server/auth/internal/handler/acceptcookiehandler.go b/server/auth/internal/handler/acceptcookiehandler.go
new file mode 100644
index 00000000..3e0e8b44
--- /dev/null
+++ b/server/auth/internal/handler/acceptcookiehandler.go
@@ -0,0 +1,35 @@
+package handler
+
+import (
+ "net/http"
+ "reflect"
+
+ "fusenapi/utils/basic"
+
+ "fusenapi/server/auth/internal/logic"
+ "fusenapi/server/auth/internal/svc"
+ "fusenapi/server/auth/internal/types"
+)
+
+func AcceptCookieHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+
+ var req types.Request
+ userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
+ if err != nil {
+ return
+ }
+
+ // 创建一个业务逻辑层实例
+ l := logic.NewAcceptCookieLogic(r.Context(), svcCtx)
+
+ rl := reflect.ValueOf(l)
+ basic.BeforeLogic(w, r, rl)
+
+ resp := l.AcceptCookie(&req, userinfo)
+
+ if !basic.AfterLogic(w, r, rl, resp) {
+ basic.NormalAfterLogic(w, r, resp)
+ }
+ }
+}
diff --git a/server/auth/internal/handler/routes.go b/server/auth/internal/handler/routes.go
new file mode 100644
index 00000000..3e951654
--- /dev/null
+++ b/server/auth/internal/handler/routes.go
@@ -0,0 +1,37 @@
+// Code generated by goctl. DO NOT EDIT.
+package handler
+
+import (
+ "net/http"
+
+ "fusenapi/server/auth/internal/svc"
+
+ "github.com/zeromicro/go-zero/rest"
+)
+
+func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
+ server.AddRoutes(
+ []rest.Route{
+ {
+ Method: http.MethodPost,
+ Path: "/api/auth/login",
+ Handler: UserLoginHandler(serverCtx),
+ },
+ {
+ Method: http.MethodPost,
+ Path: "/api/user/accept-cookie",
+ Handler: AcceptCookieHandler(serverCtx),
+ },
+ {
+ Method: http.MethodGet,
+ Path: "/api/user/oauth2/login/google",
+ Handler: UserGoogleLoginHandler(serverCtx),
+ },
+ {
+ Method: http.MethodGet,
+ Path: "/api/user/oauth2/login/register",
+ Handler: UserEmailRegisterHandler(serverCtx),
+ },
+ },
+ )
+}
diff --git a/server/home-user-auth/internal/handler/useremailregisterhandler.go b/server/auth/internal/handler/useremailregisterhandler.go
similarity index 81%
rename from server/home-user-auth/internal/handler/useremailregisterhandler.go
rename to server/auth/internal/handler/useremailregisterhandler.go
index 5d274809..bf073982 100644
--- a/server/home-user-auth/internal/handler/useremailregisterhandler.go
+++ b/server/auth/internal/handler/useremailregisterhandler.go
@@ -6,9 +6,9 @@ import (
"fusenapi/utils/basic"
- "fusenapi/server/home-user-auth/internal/logic"
- "fusenapi/server/home-user-auth/internal/svc"
- "fusenapi/server/home-user-auth/internal/types"
+ "fusenapi/server/auth/internal/logic"
+ "fusenapi/server/auth/internal/svc"
+ "fusenapi/server/auth/internal/types"
)
func UserEmailRegisterHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
diff --git a/server/home-user-auth/internal/handler/usergoogleloginhandler.go b/server/auth/internal/handler/usergoogleloginhandler.go
similarity index 81%
rename from server/home-user-auth/internal/handler/usergoogleloginhandler.go
rename to server/auth/internal/handler/usergoogleloginhandler.go
index 154b2450..fd1f54f6 100644
--- a/server/home-user-auth/internal/handler/usergoogleloginhandler.go
+++ b/server/auth/internal/handler/usergoogleloginhandler.go
@@ -6,9 +6,9 @@ import (
"fusenapi/utils/basic"
- "fusenapi/server/home-user-auth/internal/logic"
- "fusenapi/server/home-user-auth/internal/svc"
- "fusenapi/server/home-user-auth/internal/types"
+ "fusenapi/server/auth/internal/logic"
+ "fusenapi/server/auth/internal/svc"
+ "fusenapi/server/auth/internal/types"
)
func UserGoogleLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
diff --git a/server/home-user-auth/internal/handler/userloginhandler.go b/server/auth/internal/handler/userloginhandler.go
similarity index 80%
rename from server/home-user-auth/internal/handler/userloginhandler.go
rename to server/auth/internal/handler/userloginhandler.go
index d08232d6..2e32b702 100644
--- a/server/home-user-auth/internal/handler/userloginhandler.go
+++ b/server/auth/internal/handler/userloginhandler.go
@@ -6,9 +6,9 @@ import (
"fusenapi/utils/basic"
- "fusenapi/server/home-user-auth/internal/logic"
- "fusenapi/server/home-user-auth/internal/svc"
- "fusenapi/server/home-user-auth/internal/types"
+ "fusenapi/server/auth/internal/logic"
+ "fusenapi/server/auth/internal/svc"
+ "fusenapi/server/auth/internal/types"
)
func UserLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
diff --git a/server/auth/internal/logic/acceptcookielogic.go b/server/auth/internal/logic/acceptcookielogic.go
new file mode 100644
index 00000000..730bd493
--- /dev/null
+++ b/server/auth/internal/logic/acceptcookielogic.go
@@ -0,0 +1,43 @@
+package logic
+
+import (
+ "fusenapi/utils/auth"
+ "fusenapi/utils/basic"
+
+ "context"
+
+ "fusenapi/server/auth/internal/svc"
+ "fusenapi/server/auth/internal/types"
+
+ "github.com/zeromicro/go-zero/core/logx"
+)
+
+type AcceptCookieLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+}
+
+func NewAcceptCookieLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AcceptCookieLogic {
+ return &AcceptCookieLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+// 处理进入前逻辑w,r
+// func (l *AcceptCookieLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
+// }
+
+// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
+// func (l *AcceptCookieLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
+// // httpx.OkJsonCtx(r.Context(), w, resp)
+// }
+
+func (l *AcceptCookieLogic) AcceptCookie(req *types.Request, userinfo *auth.UserInfo) (resp *basic.Response) {
+ // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
+ // userinfo 传入值时, 一定不为null
+
+ return resp.SetStatus(basic.CodeOK)
+}
diff --git a/server/home-user-auth/internal/logic/useremailregisterlogic.go b/server/auth/internal/logic/useremailregisterlogic.go
similarity index 84%
rename from server/home-user-auth/internal/logic/useremailregisterlogic.go
rename to server/auth/internal/logic/useremailregisterlogic.go
index eb276e5b..c8e4751f 100644
--- a/server/home-user-auth/internal/logic/useremailregisterlogic.go
+++ b/server/auth/internal/logic/useremailregisterlogic.go
@@ -6,8 +6,8 @@ import (
"context"
- "fusenapi/server/home-user-auth/internal/svc"
- "fusenapi/server/home-user-auth/internal/types"
+ "fusenapi/server/auth/internal/svc"
+ "fusenapi/server/auth/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
@@ -30,8 +30,9 @@ func NewUserEmailRegisterLogic(ctx context.Context, svcCtx *svc.ServiceContext)
// func (l *UserEmailRegisterLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
// }
-// 处理逻辑后 w,r 如:重定向
+// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
// func (l *UserEmailRegisterLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
+// // httpx.OkJsonCtx(r.Context(), w, resp)
// }
func (l *UserEmailRegisterLogic) UserEmailRegister(req *types.RequestEmailRegister, userinfo *auth.UserInfo) (resp *basic.Response) {
diff --git a/server/auth/internal/logic/usergoogleloginlogic.go b/server/auth/internal/logic/usergoogleloginlogic.go
new file mode 100644
index 00000000..3bdad6bf
--- /dev/null
+++ b/server/auth/internal/logic/usergoogleloginlogic.go
@@ -0,0 +1,177 @@
+package logic
+
+import (
+ "fmt"
+ "fusenapi/utils/auth"
+ "fusenapi/utils/basic"
+ "log"
+ "net/http"
+ "time"
+
+ "context"
+
+ "fusenapi/server/auth/internal/svc"
+ "fusenapi/server/auth/internal/types"
+
+ "github.com/474420502/requests"
+ "github.com/zeromicro/go-zero/core/logx"
+ "github.com/zeromicro/go-zero/rest/httpx"
+ "golang.org/x/net/proxy"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/google"
+ "gorm.io/gorm"
+)
+
+type UserGoogleLoginLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+
+ token string // 登录 token
+
+ isRegistered bool // 是否注册
+ registerToken string // 注册邮箱的token
+ oauthinfo *auth.OAuthInfo
+}
+
+func NewUserGoogleLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserGoogleLoginLogic {
+ return &UserGoogleLoginLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+// 处理进入前逻辑w,r
+// func (l *UserGoogleLoginLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
+// }
+
+// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
+func (l *UserGoogleLoginLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
+
+ if resp.Code == 200 {
+
+ if !l.isRegistered {
+ now := time.Now()
+ rtoken, err := auth.GenerateRegisterToken(
+ &l.svcCtx.Config.Auth.AccessSecret,
+ l.svcCtx.Config.Auth.AccessExpire,
+ now.Unix(),
+ l.oauthinfo.Id,
+ l.oauthinfo.Platform,
+ )
+
+ if err != nil {
+ resp.SetStatus(basic.CodeOAuthRegisterTokenErr)
+ }
+
+ l.registerToken = rtoken
+ }
+
+ rurl := fmt.Sprintf(
+ l.svcCtx.Config.MainAddress+"/oauth?token=%s&is_registered=%t®ister_token=%s",
+ l.token,
+ l.isRegistered,
+ l.registerToken,
+ )
+
+ html := fmt.Sprintf(`
+
+
+
+ Redirect
+
+
+
+
+
+ `, rurl)
+ fmt.Fprintln(w, html)
+ } else {
+ httpx.OkJson(w, resp)
+ }
+
+}
+
+func (l *UserGoogleLoginLogic) UserGoogleLogin(req *types.RequestGoogleLogin, userinfo *auth.UserInfo) (resp *basic.Response) {
+ // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
+ // userinfo 传入值时, 一定不为null
+
+ dialer, err := proxy.SOCKS5("tcp", "127.0.0.1:1080", nil, proxy.Direct)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ customClient := &http.Client{
+ Transport: &http.Transport{
+ Dial: dialer.Dial,
+ },
+ }
+
+ ctx := context.WithValue(context.Background(), oauth2.HTTPClient, customClient)
+
+ var googleOauthConfig = &oauth2.Config{
+ RedirectURL: "http://localhost:9900/api/user/oauth2/login/google",
+ ClientID: l.svcCtx.Config.OAuth.Google.Appid,
+ ClientSecret: l.svcCtx.Config.OAuth.Google.Secret,
+ Scopes: []string{"https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"},
+ Endpoint: google.Endpoint,
+ }
+
+ token, err := googleOauthConfig.Exchange(ctx, req.Code)
+ if err != nil {
+ logx.Error(err)
+ resp.SetStatus(basic.CodeApiErr)
+ }
+ ses := requests.NewSession()
+ ses.Config().SetProxy("socks5://127.0.0.1:1080") // 代理 为了测试功能
+
+ r, err := ses.Get("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + token.AccessToken).Execute()
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatus(basic.CodeOAuthGoogleApiErr)
+ }
+
+ log.Println(r.Json())
+
+ googleId := r.Json().Get("id").Int()
+ user, err := l.svcCtx.AllModels.FsUser.FindUserByGoogleId(context.TODO(), googleId)
+ if err != nil {
+ if err != gorm.ErrRecordNotFound {
+ logx.Error(err)
+ return resp.SetStatus(basic.CodeDbSqlErr)
+ }
+
+ // 进入邮件注册流程
+ if req.Email == "" {
+ return resp.SetStatus(basic.CodeOK)
+ }
+
+ // 这里是注册模块, 发邮件, 通过邮件注册确认邮箱存在
+
+ // 邮箱验证格式错误
+ if !auth.ValidateEmail(req.Email) {
+ return resp.SetStatus(basic.CodeOAuthEmailErr)
+ }
+
+ return resp.SetStatus(basic.CodeOK)
+ }
+
+ // 如果密码匹配,则生成 JWT Token。
+ nowSec := time.Now().Unix()
+ jwtToken, err := auth.GenerateJwtToken(&l.svcCtx.Config.Auth.AccessSecret, l.svcCtx.Config.Auth.AccessExpire, nowSec, user.Id, 0)
+
+ // 如果生成 JWT Token 失败,则抛出错误并返回未认证的状态码。
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatus(basic.CodeServiceErr)
+ }
+
+ l.token = jwtToken
+
+ return resp.SetStatus(basic.CodeOK)
+}
diff --git a/server/auth/internal/logic/userloginlogic.go b/server/auth/internal/logic/userloginlogic.go
new file mode 100644
index 00000000..3fb705ca
--- /dev/null
+++ b/server/auth/internal/logic/userloginlogic.go
@@ -0,0 +1,93 @@
+package logic
+
+import (
+ "errors"
+ "fmt"
+ "fusenapi/utils/auth"
+ "fusenapi/utils/basic"
+ "net/http"
+ "time"
+
+ "context"
+
+ "fusenapi/server/auth/internal/svc"
+ "fusenapi/server/auth/internal/types"
+
+ "github.com/zeromicro/go-zero/core/logx"
+ "github.com/zeromicro/go-zero/rest/httpx"
+ "gorm.io/gorm"
+)
+
+type UserLoginLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+
+ token string
+}
+
+func NewUserLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserLoginLogic {
+ return &UserLoginLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+// 处理进入前逻辑w,r
+// func (l *UserLoginLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
+// }
+
+// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
+func (l *UserLoginLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
+ if l.token != "" {
+ w.Header().Add("Authorization", fmt.Sprintf("Bearer %s", l.token))
+ }
+
+ httpx.OkJsonCtx(r.Context(), w, resp)
+}
+
+func (l *UserLoginLogic) UserLogin(req *types.RequestUserLogin, userinfo *auth.UserInfo) (resp *basic.Response) {
+ // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
+ // userinfo 传入值时, 一定不为null
+
+ // 创建一个 FsUserModel 对象 m 并实例化之,该对象用于操作 MySQL 数据库中的用户数据表。
+ m := l.svcCtx.AllModels.FsUser
+
+ // 在用户数据表中根据登录名(email)查找用户记录,并返回 UserModel 类型的结构体对象 userModel。
+ user, err := m.FindUserByEmail(l.ctx, req.Email)
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ return resp.SetStatus(basic.CodeEmailNotFoundErr)
+ }
+
+ // 如果在用户数据表中找到了登录名匹配的用户记录,则判断密码是否匹配。
+ if *user.PasswordHash != req.Password {
+ logx.Info("密码错误")
+ return resp.SetStatus(basic.CodePasswordErr)
+ }
+
+ // 如果密码匹配,则生成 JWT Token。
+ nowSec := time.Now().Unix()
+ jwtToken, err := auth.GenerateJwtToken(&l.svcCtx.Config.Auth.AccessSecret, l.svcCtx.Config.Auth.AccessExpire, nowSec, user.Id, 0)
+
+ // 如果生成 JWT Token 失败,则抛出错误并返回未认证的状态码。
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatus(basic.CodeUnAuth)
+ }
+
+ // 如果更新 VerificationToken 字段失败,则返回未认证的状态码。
+ if err != nil {
+ return resp.SetStatus(basic.CodeUnAuth)
+ }
+
+ // 构造 DataUserLogin 类型的数据对象 data 并设置其属性值为生成的 JWT Token。
+ data := &types.DataUserLogin{
+ Token: jwtToken,
+ }
+
+ l.token = jwtToken
+
+ // 返回认证成功的状态码以及数据对象 data 和 JWT Token。
+ return resp.SetStatus(basic.CodeOK, data)
+}
diff --git a/server/auth/internal/svc/servicecontext.go b/server/auth/internal/svc/servicecontext.go
new file mode 100644
index 00000000..9841ab05
--- /dev/null
+++ b/server/auth/internal/svc/servicecontext.go
@@ -0,0 +1,61 @@
+package svc
+
+import (
+ "errors"
+ "fmt"
+ "fusenapi/server/auth/internal/config"
+ "net/http"
+
+ "fusenapi/initalize"
+ "fusenapi/model/gmodel"
+
+ "github.com/golang-jwt/jwt"
+ "gorm.io/gorm"
+)
+
+type ServiceContext struct {
+ Config config.Config
+
+ MysqlConn *gorm.DB
+ AllModels *gmodel.AllModelsGen
+}
+
+func NewServiceContext(c config.Config) *ServiceContext {
+
+ return &ServiceContext{
+ Config: c,
+ MysqlConn: initalize.InitMysql(c.SourceMysql),
+ AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
+ }
+}
+
+func (svcCtx *ServiceContext) ParseJwtToken(r *http.Request) (jwt.MapClaims, error) {
+ AuthKey := r.Header.Get("Authorization")
+ if AuthKey == "" {
+ return nil, nil
+ }
+ AuthKey = AuthKey[7:]
+
+ if len(AuthKey) <= 50 {
+ return nil, errors.New(fmt.Sprint("Error parsing token, len:", len(AuthKey)))
+ }
+
+ token, err := jwt.Parse(AuthKey, func(token *jwt.Token) (interface{}, error) {
+ // 检查签名方法是否为 HS256
+ if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
+ return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
+ }
+ // 返回用于验证签名的密钥
+ return []byte(svcCtx.Config.Auth.AccessSecret), nil
+ })
+ if err != nil {
+ return nil, errors.New(fmt.Sprint("Error parsing token:", err))
+ }
+
+ // 验证成功返回
+ if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
+ return claims, nil
+ }
+
+ return nil, errors.New(fmt.Sprint("Invalid token", err))
+}
diff --git a/server/auth/internal/types/types.go b/server/auth/internal/types/types.go
new file mode 100644
index 00000000..ccb83ca7
--- /dev/null
+++ b/server/auth/internal/types/types.go
@@ -0,0 +1,101 @@
+// Code generated by goctl. DO NOT EDIT.
+package types
+
+import (
+ "fusenapi/utils/basic"
+)
+
+type RequestUserLogin struct {
+ Email string `json:"email"`
+ Password string `json:"password"`
+}
+
+type RequestGoogleLogin struct {
+ Code string `form:"code"`
+ Scope string `form:"scope"`
+ AuthUser string `form:"authuser"`
+ Prompt string `form:"prompt"`
+ Email string `form:"email,optional"`
+}
+
+type RequestEmailRegister struct {
+ Email string `json:"email"`
+ RegisterToken string `json:"register_token"`
+}
+
+type DataUserLogin struct {
+ Token string `json:"token"` // 登录jwt token
+}
+
+type DataGuest struct {
+ Token string `json:"token"` // 登录jwt token
+}
+
+type Request struct {
+}
+
+type Response struct {
+ Code int `json:"code"`
+ Message string `json:"msg"`
+ Data interface{} `json:"data"`
+}
+
+type Auth struct {
+ AccessSecret string `json:"accessSecret"`
+ AccessExpire int64 `json:"accessExpire"`
+ RefreshAfter int64 `json:"refreshAfter"`
+}
+
+type File struct {
+ Filename string `fsfile:"filename"`
+ Header map[string][]string `fsfile:"header"`
+ Size int64 `fsfile:"size"`
+ Data []byte `fsfile:"data"`
+}
+
+type Meta struct {
+ TotalCount int64 `json:"totalCount"`
+ PageCount int64 `json:"pageCount"`
+ CurrentPage int `json:"currentPage"`
+ PerPage int `json:"perPage"`
+}
+
+// Set 设置Response的Code和Message值
+func (resp *Response) Set(Code int, Message string) *Response {
+ return &Response{
+ Code: Code,
+ Message: Message,
+ }
+}
+
+// Set 设置整个Response
+func (resp *Response) SetWithData(Code int, Message string, Data interface{}) *Response {
+ return &Response{
+ Code: Code,
+ Message: Message,
+ Data: Data,
+ }
+}
+
+// SetStatus 设置默认StatusResponse(内部自定义) 默认msg, 可以带data, data只使用一个参数
+func (resp *Response) SetStatus(sr *basic.StatusResponse, data ...interface{}) *Response {
+ newResp := &Response{
+ Code: sr.Code,
+ }
+ if len(data) == 1 {
+ newResp.Data = data[0]
+ }
+ return newResp
+}
+
+// SetStatusWithMessage 设置默认StatusResponse(内部自定义) 非默认msg, 可以带data, data只使用一个参数
+func (resp *Response) SetStatusWithMessage(sr *basic.StatusResponse, msg string, data ...interface{}) *Response {
+ newResp := &Response{
+ Code: sr.Code,
+ Message: msg,
+ }
+ if len(data) == 1 {
+ newResp.Data = data[0]
+ }
+ return newResp
+}
diff --git a/server/home-user-auth/etc/home-user-auth.yaml b/server/home-user-auth/etc/home-user-auth.yaml
index 7ef5a2c9..a35c3ac8 100644
--- a/server/home-user-auth/etc/home-user-auth.yaml
+++ b/server/home-user-auth/etc/home-user-auth.yaml
@@ -1,7 +1,6 @@
Name: home-user-auth
Host: 0.0.0.0
Port: 9904
-MainAddress: "http://localhost:9900"
SourceMysql: fusentest:XErSYmLELKMnf3Dh@tcp(110.41.19.98:3306)/fusentest
Auth:
@@ -9,14 +8,5 @@ Auth:
AccessExpire: 2592000
RefreshAfter: 1592000
-OAuth:
- google:
- appid: "1064842923358-e94msq2glj6qr4lrva9ts3hqjjt53q8h.apps.googleusercontent.com"
- secret: "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"
-
- facebook:
- appid: "1095953604597065"
- secret: "b146872550a190d5275b1420c212002e"
-
Stripe:
SK: "sk_test_51IisojHygnIJZeghPVSBhkwySfcyDV4SoAduIxu3J7bvSJ9cZMD96LY1LO6SpdbYquLJX5oKvgEBB67KT9pecfCy00iEC4pp9y"
diff --git a/server/home-user-auth/internal/handler/routes.go b/server/home-user-auth/internal/handler/routes.go
index 75ac9d8f..230527b4 100644
--- a/server/home-user-auth/internal/handler/routes.go
+++ b/server/home-user-auth/internal/handler/routes.go
@@ -12,16 +12,6 @@ import (
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
- {
- Method: http.MethodPost,
- Path: "/api/user/login",
- Handler: UserLoginHandler(serverCtx),
- },
- {
- Method: http.MethodPost,
- Path: "/api/user/accept-cookie",
- Handler: AcceptCookieHandler(serverCtx),
- },
{
Method: http.MethodGet,
Path: "/api/user/fonts",
@@ -67,16 +57,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/api/user/order-delete",
Handler: UserOderDeleteHandler(serverCtx),
},
- {
- Method: http.MethodGet,
- Path: "/api/user/oauth2/login/google",
- Handler: UserGoogleLoginHandler(serverCtx),
- },
- {
- Method: http.MethodGet,
- Path: "/api/user/oauth2/login/register",
- Handler: UserEmailRegisterHandler(serverCtx),
- },
{
Method: http.MethodGet,
Path: "/api/user/order-list",
diff --git a/server/home-user-auth/internal/logic/email_manager.go b/server/home-user-auth/internal/logic/email_manager.go
new file mode 100644
index 00000000..60e600af
--- /dev/null
+++ b/server/home-user-auth/internal/logic/email_manager.go
@@ -0,0 +1,161 @@
+package logic
+
+import (
+ "bytes"
+ "log"
+ "net/smtp"
+ "sync"
+ "text/template"
+ "time"
+)
+
+var EmailManager *EmailSender
+
+// EmailSender
+type EmailSender struct {
+ lock sync.Mutex
+ EmailTasks chan string // 处理email的队列
+ Auth smtp.Auth // 邮箱发送处理
+ FromEmail string // 发送的email, 公司email
+ emailSending map[string]*EmailTask // 正在发送的邮件
+ ResendTimeLimit time.Duration // 重发时间限制
+}
+
+// EmailTask
+type EmailTask struct {
+ Email string // email
+ SendTime time.Time // 处理的任务时间
+}
+
+// ProcessEmailTasks 处理邮件队列
+func (m *EmailSender) ProcessEmailTasks() {
+ for {
+ emailTarget, ok := <-m.EmailTasks
+ if !ok {
+ log.Println("Email task channel closed")
+ break
+ }
+
+ m.lock.Lock()
+ _, isSending := m.emailSending[emailTarget]
+ if isSending {
+ m.lock.Unlock()
+ continue
+ }
+
+ m.emailSending[emailTarget] = &EmailTask{
+ Email: emailTarget,
+ SendTime: time.Now(),
+ }
+ m.lock.Unlock()
+
+ // TODO: Replace with actual email content
+ content := []byte("Hello, this is a test email")
+ err := smtp.SendMail(emailTarget, m.Auth, m.FromEmail, []string{emailTarget}, content)
+ if err != nil {
+ log.Printf("Failed to send email to %s: %v\n", emailTarget, err)
+ m.Resend(emailTarget, content)
+ }
+ }
+}
+
+// Resend 重发邮件
+func (m *EmailSender) Resend(emailTarget string, content []byte) {
+ time.Sleep(m.ResendTimeLimit)
+
+ m.lock.Lock()
+ defer m.lock.Unlock()
+
+ // Check if the email task still exists and has not been sent successfully
+ if task, ok := m.emailSending[emailTarget]; ok && task.SendTime.Add(m.ResendTimeLimit).After(time.Now()) {
+ err := smtp.SendMail(emailTarget, m.Auth, m.FromEmail, []string{emailTarget}, content)
+ if err != nil {
+ log.Printf("Failed to resend email to %s: %v\n", emailTarget, err)
+ } else {
+ delete(m.emailSending, emailTarget)
+ }
+ }
+}
+
+// ClearExpiredTasks 清除过期的邮件任务
+func (m *EmailSender) ClearExpiredTasks() {
+ ticker := time.NewTicker(time.Minute)
+ defer ticker.Stop()
+
+ for {
+ <-ticker.C
+
+ m.lock.Lock()
+ for email, task := range m.emailSending {
+ if task.SendTime.Add(m.ResendTimeLimit).Before(time.Now()) {
+ delete(m.emailSending, email)
+ }
+ }
+ m.lock.Unlock()
+ }
+}
+
+func init() {
+
+ // Initialize the email manager
+ EmailManager = &EmailSender{
+ EmailTasks: make(chan string, 10),
+ Auth: smtp.PlainAuth(
+ "",
+ "user@example.com",
+ "password",
+ "smtp.gmail.com",
+ ),
+ FromEmail: "user@example.com",
+ emailSending: make(map[string]*EmailTask, 10),
+ ResendTimeLimit: time.Minute * 1,
+ }
+
+ // Start processing email tasks
+ go EmailManager.ProcessEmailTasks()
+
+ // Start clearing expired tasks
+ go EmailManager.ClearExpiredTasks()
+}
+
+const emailTemplate = `Subject: Your {{.CompanyName}} Account Confirmation
+
+Dear
+
+Thank you for creating an account with {{.CompanyName}}. We're excited to have you on board!
+
+Before we get started, we just need to confirm that this is the right email address. Please confirm your email address by clicking on the link below:
+
+{{.ConfirmationLink}}
+
+Once you've confirmed, you can get started with {{.CompanyName}}. If you have any questions, feel free to reply to this email. We're here to help!
+
+If you did not create an account with us, please ignore this email.
+
+Thanks,
+{{.SenderName}}
+{{.SenderTitle}}
+{{.CompanyName}}
+`
+
+func RenderEmailTemplate(companyName, recipient, confirmationLink, senderName, senderTitle string) string {
+ tmpl, err := template.New("email").Parse(emailTemplate)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ data := map[string]string{
+ "CompanyName": companyName,
+ "ConfirmationLink": confirmationLink,
+ "SenderName": senderName,
+ "SenderTitle": senderTitle,
+ }
+
+ var result bytes.Buffer
+ err = tmpl.Execute(&result, data)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ return result.String()
+}
diff --git a/server/home-user-auth/internal/logic/usergoogleloginlogic.go b/server/home-user-auth/internal/logic/usergoogleloginlogic.go
index 8c31f753..7ad4958a 100644
--- a/server/home-user-auth/internal/logic/usergoogleloginlogic.go
+++ b/server/home-user-auth/internal/logic/usergoogleloginlogic.go
@@ -6,7 +6,6 @@ import (
"fusenapi/utils/basic"
"log"
"net/http"
- "net/url"
"time"
"context"
@@ -16,6 +15,7 @@ import (
"github.com/474420502/requests"
"github.com/zeromicro/go-zero/core/logx"
+ "github.com/zeromicro/go-zero/rest/httpx"
"golang.org/x/net/proxy"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
@@ -31,6 +31,7 @@ type UserGoogleLoginLogic struct {
isRegistered bool // 是否注册
registerToken string // 注册邮箱的token
+ oauthinfo *auth.OAuthInfo
}
func NewUserGoogleLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserGoogleLoginLogic {
@@ -47,29 +48,52 @@ func NewUserGoogleLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *U
func (l *UserGoogleLoginLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
- rurl := fmt.Sprintf(
- l.svcCtx.Config.MainAddress+"/oauth?token=%s&is_registered=%t®ister_token=%s",
- l.token,
- l.isRegistered,
- l.registerToken,
- )
+ if resp.Code == 200 {
- html := fmt.Sprintf(`
-
-
-
- Redirect
-
-
-
-
-
- `, rurl)
- fmt.Fprintln(w, html)
+
+ l.registerToken = rtoken
+ }
+
+ rurl := fmt.Sprintf(
+ l.svcCtx.Config.MainAddress+"/oauth?token=%s&is_registered=%t®ister_token=%s",
+ l.token,
+ l.isRegistered,
+ l.registerToken,
+ )
+
+ html := fmt.Sprintf(`
+
+
+
+ Redirect
+
+
+
+
+
+ `, rurl)
+ fmt.Fprintln(w, html)
+ } else {
+ httpx.OkJson(w, resp)
+ }
+
}
func (l *UserGoogleLoginLogic) UserGoogleLogin(req *types.RequestGoogleLogin, userinfo *auth.UserInfo) (resp *basic.Response) {
@@ -114,36 +138,39 @@ func (l *UserGoogleLoginLogic) UserGoogleLogin(req *types.RequestGoogleLogin, us
log.Println(r.Json())
googleId := r.Json().Get("id").Int()
-
- // l.redirectUrl = "http://localhost:9900/oauth?token=21321123&is_registered"
- // return resp.Set(304, "21321321")
user, err := l.svcCtx.AllModels.FsUser.FindUserByGoogleId(context.TODO(), googleId)
- log.Println(user)
if err != nil {
if err != gorm.ErrRecordNotFound {
logx.Error(err)
return resp.SetStatus(basic.CodeDbSqlErr)
}
+ // 进入邮件注册流程
if req.Email == "" {
return resp.SetStatus(basic.CodeOK)
}
- // 如果密码匹配,则生成 JWT Token。
- nowSec := time.Now().Unix()
- jwtToken, err := auth.GenerateJwtToken(&l.svcCtx.Config.Auth.AccessSecret, l.svcCtx.Config.Auth.AccessExpire, nowSec, 0, 0)
+ // 这里是注册模块, 发邮件, 通过邮件注册确认邮箱存在
- // 如果生成 JWT Token 失败,则抛出错误并返回未认证的状态码。
- if err != nil {
- logx.Error(err)
- return resp.SetStatus(basic.CodeServiceErr)
+ // 邮箱验证格式错误
+ if !auth.ValidateEmail(req.Email) {
+ return resp.SetStatus(basic.CodeOAuthEmailErr)
}
- return resp.SetRewriteHandler(func(w http.ResponseWriter, r *http.Request) {
- http.Redirect(w, r, "http://localhost:9900?token="+url.QueryEscape(jwtToken), http.StatusFound)
- })
-
+ return resp.SetStatus(basic.CodeOK)
}
+ // 如果密码匹配,则生成 JWT Token。
+ nowSec := time.Now().Unix()
+ jwtToken, err := auth.GenerateJwtToken(&l.svcCtx.Config.Auth.AccessSecret, l.svcCtx.Config.Auth.AccessExpire, nowSec, user.Id, 0)
+
+ // 如果生成 JWT Token 失败,则抛出错误并返回未认证的状态码。
+ if err != nil {
+ logx.Error(err)
+ return resp.SetStatus(basic.CodeServiceErr)
+ }
+
+ l.token = jwtToken
+
return resp.SetStatus(basic.CodeOK)
}
diff --git a/server/home-user-auth/internal/types/types.go b/server/home-user-auth/internal/types/types.go
index cdb5446a..bf8211ab 100644
--- a/server/home-user-auth/internal/types/types.go
+++ b/server/home-user-auth/internal/types/types.go
@@ -70,19 +70,6 @@ type Product struct {
IsStop int64 `json:"is_stop"`
}
-type RequestGoogleLogin struct {
- Code string `form:"code"`
- Scope string `form:"scope"`
- AuthUser string `form:"authuser"`
- Prompt string `form:"prompt"`
- Email string `form:"email,optional"`
-}
-
-type RequestEmailRegister struct {
- Email string `json:"email"`
- RegisterToken string `json:"register_token"`
-}
-
type RequestContactService struct {
Type string `json:"type"` // 类型
RelationID int64 `json:"relation_id"` // 关系id
@@ -108,11 +95,6 @@ type RequestBasicInfoForm struct {
IsRemoveBg int64 `json:"is_remove_bg"` // 用户上传logo是否去除背景
}
-type RequestUserLogin struct {
- Email string `json:"email"`
- Password string `json:"password"`
-}
-
type RequestAddAddress struct {
Id int64 `json:"id"` // address_id 地址id
IsDefault int64 `json:"is_default"` //是否默认
diff --git a/server_api/auth.api b/server_api/auth.api
new file mode 100644
index 00000000..2460b9b6
--- /dev/null
+++ b/server_api/auth.api
@@ -0,0 +1,53 @@
+syntax = "v1"
+
+info (
+ title: // TODO: add title
+ desc: // TODO: add description
+ author: ""
+ email: ""
+)
+
+import "basic.api"
+
+service auth {
+ @handler UserLoginHandler
+ post /api/auth/login(RequestUserLogin) returns (response);
+
+ @handler AcceptCookieHandler
+ post /api/user/accept-cookie(request) returns (response);
+
+ @handler UserGoogleLoginHandler
+ get /api/user/oauth2/login/google(RequestGoogleLogin) returns (response);
+
+ @handler UserEmailRegisterHandler
+ get /api/user/oauth2/login/register(RequestEmailRegister) returns (response);
+}
+
+// UserAddAddressHandler 用户登录请求结构
+type RequestUserLogin {
+ Email string `json:"email"`
+ Password string `json:"password"`
+}
+
+type RequestGoogleLogin {
+ Code string `form:"code"`
+ Scope string `form:"scope"`
+ AuthUser string `form:"authuser"`
+ Prompt string `form:"prompt"`
+ Email string `form:"email,optional"`
+}
+
+type RequestEmailRegister {
+ Email string `json:"email"`
+ RegisterToken string `json:"register_token"`
+}
+
+// UserLoginHandler 用户登录请求结构
+type DataUserLogin {
+ Token string `json:"token"` // 登录jwt token
+}
+
+// DataGuest 游客获取toekn请求结构
+type DataGuest {
+ Token string `json:"token"` // 登录jwt token
+}
\ No newline at end of file
diff --git a/server_api/home-user-auth.api b/server_api/home-user-auth.api
index fdc7594e..d36da50b 100644
--- a/server_api/home-user-auth.api
+++ b/server_api/home-user-auth.api
@@ -14,12 +14,6 @@ service home-user-auth {
// @handler UserRegisterHandler
// post /api/user/register(RequestUserRegister) returns (response);
- @handler UserLoginHandler
- post /api/user/login(RequestUserLogin) returns (response);
-
- @handler AcceptCookieHandler
- post /api/user/accept-cookie(request) returns (response);
-
@handler UserFontsHandler
get /api/user/fonts(request) returns (response);
@@ -50,12 +44,6 @@ service home-user-auth {
@handler UserOderDeleteHandler
post /api/user/order-delete(RequestOrderId) returns (response);
- @handler UserGoogleLoginHandler
- get /api/user/oauth2/login/google(RequestGoogleLogin) returns (response);
-
- @handler UserEmailRegisterHandler
- get /api/user/oauth2/login/register(RequestEmailRegister) returns (response);
-
//订单列表
@handler UserOrderListHandler
get /api/user/order-list (UserOrderListReq) returns (response);
@@ -136,19 +124,6 @@ type Product {
IsStop int64 `json:"is_stop"`
}
-type RequestGoogleLogin {
- Code string `form:"code"`
- Scope string `form:"scope"`
- AuthUser string `form:"authuser"`
- Prompt string `form:"prompt"`
- Email string `form:"email,optional"`
-}
-
-type RequestEmailRegister {
- Email string `json:"email"`
- RegisterToken string `json:"register_token"`
-}
-
type RequestContactService {
Type string `json:"type"` // 类型
RelationID int64 `json:"relation_id"` // 关系id
@@ -176,12 +151,6 @@ type RequestBasicInfoForm {
// NewPassword string `form:"new_password,optional" db:"new_password"` // new_password 如果存在新密码
}
-// UserAddAddressHandler 用户登录请求结构
-type RequestUserLogin {
- Email string `json:"email"`
- Password string `json:"password"`
-}
-
// RequestAddAddress 增加地址结构
type RequestAddAddress {
Id int64 `json:"id"` // address_id 地址id
@@ -204,15 +173,7 @@ type RequestOrderId {
RefundReason string `json:"refund_reason"` //取消原因
}
-// UserLoginHandler 用户登录请求结构
-type DataUserLogin {
- Token string `json:"token"` // 登录jwt token
-}
-// DataGuest 游客获取toekn请求结构
-type DataGuest {
- Token string `json:"token"` // 登录jwt token
-}
// UserBasicInfoHandler 返回data结构
type DataUserBasicInfo {
diff --git a/utils/auth/user.go b/utils/auth/user.go
index 3acb8249..9d0e5a89 100644
--- a/utils/auth/user.go
+++ b/utils/auth/user.go
@@ -68,6 +68,11 @@ type BackendUserInfo struct {
DepartmentId int64 `json:"department_id"`
}
+type OAuthInfo struct {
+ Id int64 `json:"id"`
+ Platform string `json:"platform"`
+}
+
// 获取登录信息
func GetUserInfoFormMapClaims(claims jwt.MapClaims) (*UserInfo, error) {
userinfo := &UserInfo{}
@@ -195,3 +200,79 @@ func CheckValueRange[T comparable](v T, rangevalues ...T) bool {
}
return false
}
+
+// GenerateRegisterToken 网站注册 token生成
+func GenerateRegisterToken(accessSecret *string, accessExpire, nowSec int64, id int64, platform string) (string, error) {
+ claims := make(jwt.MapClaims)
+ claims["exp"] = nowSec + accessExpire
+ claims["iat"] = nowSec
+
+ if id == 0 {
+ err := errors.New("userid and guestid cannot be 0 at the same time")
+ logx.Error(err)
+ return "", err
+
+ }
+ claims["id"] = id
+ claims["platform"] = platform
+
+ token := jwt.New(jwt.SigningMethodHS256)
+ token.Claims = claims
+ return token.SignedString([]byte(*accessSecret))
+}
+
+// GetRegisterFormMapClaims 获取注册唯一token标识登录信息
+func GetRegisterFormMapClaims(claims jwt.MapClaims) (*OAuthInfo, error) {
+ oauthinfo := &OAuthInfo{}
+ if userid, ok := claims["id"]; ok {
+ uid, ok := userid.(float64)
+ if !ok {
+ err := errors.New(fmt.Sprint("parse uid form context err:", userid))
+ logx.Error("parse uid form context err:", err)
+ return nil, err
+ }
+ oauthinfo.Id = int64(uid)
+ } else {
+ err := errors.New(`id not in claims`)
+ logx.Error(`id not in claims`)
+ return nil, err
+ }
+
+ if splatform, ok := claims["id"]; ok {
+ platform, ok := splatform.(string)
+ if !ok {
+ err := errors.New(fmt.Sprint("parse uid form context err:", platform))
+ logx.Error("parse uid form context err:", err)
+ return nil, err
+ }
+ oauthinfo.Platform = platform
+ } else {
+ err := errors.New(`id not in claims`)
+ logx.Error(`id not in claims`)
+ return nil, err
+ }
+
+ return oauthinfo, nil
+}
+
+func getRegisterJwtClaims(Token string, AccessSecret *string) (jwt.MapClaims, error) {
+
+ token, err := jwt.Parse(Token, func(token *jwt.Token) (interface{}, error) {
+ // 检查签名方法是否为 HS256
+ if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
+ return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
+ }
+ // 返回用于验证签名的密钥
+ return []byte(*AccessSecret), nil
+ })
+ if err != nil {
+ return nil, errors.New(fmt.Sprint("Error parsing token:", err))
+ }
+
+ // 验证成功返回
+ if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
+ return claims, nil
+ }
+
+ return nil, errors.New(fmt.Sprint("Invalid token", err))
+}
diff --git a/utils/basic/basic.go b/utils/basic/basic.go
index 7ec3d02f..6a3c8349 100644
--- a/utils/basic/basic.go
+++ b/utils/basic/basic.go
@@ -39,7 +39,9 @@ var (
CodeServiceErr = &StatusResponse{510, "server logic error"} // 服务逻辑错误
CodeUnAuth = &StatusResponse{401, "unauthorized"} // 未授权
- CodeOAuthGoogleApiErr = &StatusResponse{5070, "oauth2 google api error"}
+ CodeOAuthGoogleApiErr = &StatusResponse{5070, "oauth2 google api error"}
+ CodeOAuthRegisterTokenErr = &StatusResponse{5071, "oauth2 jwt token error"}
+ CodeOAuthEmailErr = &StatusResponse{5071, "Invalid email format"}
CodeS3PutObjectRequestErr = &StatusResponse{5060, "s3 PutObjectRequest error"} // s3 PutObjectRequest 错误
CodeS3PutSizeLimitErr = &StatusResponse{5061, "s3 over limit size error"} // s3 超过文件大小限制 错误