diff --git a/api/request/tokenApi.go b/api/request/tokenApi.go new file mode 100644 index 0000000..b59259a --- /dev/null +++ b/api/request/tokenApi.go @@ -0,0 +1,9 @@ +package request + +import "github.com/gogf/gf/v2/frame/g" + +type TokenCreateReq struct { + g.Meta `path:"/create" tags:"创建" method:"get" summary:"创建 Token"` +} + +type TokenCreateRes struct{} diff --git a/internal/controller/auth/token/token.go b/internal/controller/auth/token/token.go new file mode 100644 index 0000000..4604d32 --- /dev/null +++ b/internal/controller/auth/token/token.go @@ -0,0 +1,11 @@ +package token + +import ( + "PersonalMain/api" +) + +type ControllerV1 struct{} + +func NewTokenV1() api.ITokenV1 { + return &ControllerV1{} +} diff --git a/internal/controller/auth/token/tokenController.go b/internal/controller/auth/token/tokenController.go new file mode 100644 index 0000000..59a0a00 --- /dev/null +++ b/internal/controller/auth/token/tokenController.go @@ -0,0 +1,36 @@ +package token + +import ( + "PersonalMain/api/request" + "PersonalMain/internal/model/do" + "PersonalMain/internal/service" + "PersonalMain/utility" + "context" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" +) + +func (_ *ControllerV1) TokenCreate(ctx context.Context, _ *request.TokenCreateReq) (res *request.TokenCreateRes, err error) { + // 获取 Cookie 是否存在 + req := ghttp.RequestFromCtx(ctx) + hasCookie := req.Cookie.Contains("token") + tokenService := service.NewTokenService() + var token *do.TokenDO + if hasCookie { + // 检查 Session 是否有效 + token = tokenService.GetToken(req) + if tokenService.VerifyToken(token) { + // 有效则输出Token依然有效 + utility.Success(req, "Token 依然有效", nil) + } else { + // 生成新的 Session + token = tokenService.CreateToken() + utility.Success(req, "Token 已重新生成", g.Map{"token": token.Token}) + } + } else { + // 生成新的 Session + token = tokenService.CreateToken() + utility.Success(req, "Token 已生成", g.Map{"token": token.Token}) + } + return res, err +} diff --git a/internal/dao/tokenDAO/tokenDAO.go b/internal/dao/tokenDAO/tokenDAO.go new file mode 100644 index 0000000..1cc022a --- /dev/null +++ b/internal/dao/tokenDAO/tokenDAO.go @@ -0,0 +1,69 @@ +package tokenDAO + +import ( + "PersonalMain/internal/model/do" + "PersonalMain/utility/Processing" + "context" + "github.com/gogf/gf/v2/frame/g" + "time" +) + +// CreateToken +// +// 创建Token业务 +func CreateToken() do.TokenDO { + token := do.TokenDO{ + Id: nil, + UserId: nil, + Token: Processing.CreateToken(), + ExpiredAt: time.Now().Add(time.Minute * 10), + CreatedAt: time.Now(), + } + _, err := g.Model("xf_token").Data(token).OmitEmpty().Insert() + if err == nil { + g.Log().Cat("Database").Cat("Token").Debug(context.TODO(), "Token", token.Token, "创建成功") + return token + } else { + g.Log().Cat("Database").Cat("Token").Error(context.TODO(), err.Error()) + return do.TokenDO{} + } +} + +// GetToken +// +// 获取Token业务 +func GetToken(token string) *do.TokenDO { + var tokenDO do.TokenDO + result, err := g.Model("xf_token").Where("token = ?", token).One() + if err == nil { + // 检查数据库是否为空 + if !result.IsEmpty() { + err := result.Struct(&tokenDO) + if err != nil { + g.Log().Cat("Database").Cat("Token").Error(context.TODO(), err.Error()) + return nil + } else { + g.Log().Cat("Database").Cat("Token").Debug(context.TODO(), "Token", tokenDO.Token, "获取成功") + return &tokenDO + } + } else { + g.Log().Cat("Database").Cat("Token").Debug(context.TODO(), "xf_token 数据表为空") + return nil + } + } else { + g.Log().Cat("Database").Cat("Token").Error(context.TODO(), err.Error()) + return nil + } +} + +// DeleteToken +// +// 删除Token业务 +func DeleteToken(token string) { + _, err := g.Model("xf_token").Where("token = ?", token).Delete() + if err != nil { + g.Log().Cat("Database").Cat("Token").Error(context.TODO(), err.Error()) + } else { + g.Log().Cat("Database").Cat("Token").Debug(context.TODO(), "Token", token, "删除成功") + } +} diff --git a/internal/logic/tokenServiceImpl.go b/internal/logic/tokenServiceImpl.go new file mode 100644 index 0000000..c357d09 --- /dev/null +++ b/internal/logic/tokenServiceImpl.go @@ -0,0 +1,54 @@ +package logic + +import ( + "PersonalMain/internal/dao/tokenDAO" + "PersonalMain/internal/model/do" + "github.com/gogf/gf/v2/net/ghttp" + "time" +) + +type DefaultTokenImpl struct{} + +// CreateToken +// +// 创建Token业务 +func (_ DefaultTokenImpl) CreateToken() *do.TokenDO { + token := tokenDAO.CreateToken() + // 检查数据库中是否存在该 token + return &token +} + +// GetToken +// +// 获取Token业务 +func (_ DefaultTokenImpl) GetToken(req *ghttp.Request) *do.TokenDO { + // 获取 Cookie 中的 token + cookieToken := req.Cookie.Get("token") + if cookieToken != nil { + // 数据库查找 token + token := tokenDAO.GetToken(cookieToken.String()) + // 检查数据库中是否存在该 token + if token != nil { + // 检查Token是否超时 + return token + } + } + return nil +} + +// VerifyToken +// +// 验证Token是否有效 +func (_ DefaultTokenImpl) VerifyToken(token *do.TokenDO) bool { + if token != nil { + if token.ExpiredAt.After(time.Now()) { + return true + } else { + // 删除数据库 + tokenDAO.DeleteToken(token.Token) + return false + } + } else { + return false + } +} diff --git a/internal/model/do/tokenDO.go b/internal/model/do/tokenDO.go new file mode 100644 index 0000000..a0bc1bf --- /dev/null +++ b/internal/model/do/tokenDO.go @@ -0,0 +1,13 @@ +package do + +import ( + "time" +) + +type TokenDO struct { + Id *int64 `json:"id"` + UserId *int64 `json:"user_id"` + Token string `json:"token"` + ExpiredAt time.Time `json:"expired_at"` + CreatedAt time.Time `json:"created_at"` +} diff --git a/internal/service/tokenService.go b/internal/service/tokenService.go new file mode 100644 index 0000000..78af367 --- /dev/null +++ b/internal/service/tokenService.go @@ -0,0 +1,20 @@ +package service + +import ( + "PersonalMain/internal/logic" + "PersonalMain/internal/model/do" + "github.com/gogf/gf/v2/net/ghttp" +) + +func NewTokenService() TokenService { + return &logic.DefaultTokenImpl{} +} + +// TokenService +// +// Token 服务接口 +type TokenService interface { + CreateToken() *do.TokenDO + GetToken(req *ghttp.Request) *do.TokenDO + VerifyToken(token *do.TokenDO) bool +}