From 4aa5a62d7d1e40f9954bbbac35ed6019965411da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=85=A2=E9=B8=9F?= Date: Tue, 26 Dec 2023 23:08:48 +0800 Subject: [PATCH] =?UTF-8?q?user=5Fv1=20basic=20=E5=9F=BA=E7=A1=80=E8=AE=A4?= =?UTF-8?q?=E8=AF=81=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- configs/main.yaml | 5 +++ internal/basic/auth/user_token.go | 46 +++++++++++++++++++++ internal/basic/config/main.go | 5 +++ internal/server/http.go | 65 +----------------------------- internal/server/http_middleware.go | 50 +++++++++++++++++++++++ internal/server/router_config.go | 46 +++++++++++++++++++++ internal/server/router_log.go | 29 +++++++++++++ 7 files changed, 183 insertions(+), 63 deletions(-) create mode 100644 internal/basic/auth/user_token.go create mode 100644 internal/server/http_middleware.go create mode 100644 internal/server/router_config.go create mode 100644 internal/server/router_log.go diff --git a/configs/main.yaml b/configs/main.yaml index 13ec05a..160a9bc 100644 --- a/configs/main.yaml +++ b/configs/main.yaml @@ -9,3 +9,8 @@ task: ## 加密 crypto: secret: '12345678' # 秘钥 至少8位数字,否则无效 + +## 用户 +user: + admin_account: "admin" # 管理员账号,设置后页面请求需要登录 + admin_password: "" # 管理员密码 \ No newline at end of file diff --git a/internal/basic/auth/user_token.go b/internal/basic/auth/user_token.go new file mode 100644 index 0000000..cb5b563 --- /dev/null +++ b/internal/basic/auth/user_token.go @@ -0,0 +1,46 @@ +package auth + +import ( + "cron/internal/basic/config" + "errors" + "github.com/gin-gonic/gin" +) + +const ( + // http授权Header名称 + httpAuthHeader = "Authorization" +) + +// 令牌用户信息 +type UserToken struct { + //Env int `json:"env"` + //UserId int `json:"user_id"` + UserName string `json:"user_name"` +} + +// 解析http令牌 +func ParseHttpToken(ctx *gin.Context) (u *UserToken, err error) { + conf := config.MainConf().User + // 不校验账号 + if conf == nil || conf.AdminAccount == "" { + return &UserToken{UserName: "无"}, nil + } + account, password, ok := ctx.Request.BasicAuth() + if !ok { + return nil, errors.New("401 Unauthorized!") + } + if account != conf.AdminAccount || password != conf.AdminPassword { + return nil, errors.New("401 Password error!") + } + + u = &UserToken{UserName: "管理员"} + return u, nil +} + +func GetUser(ctx *gin.Context) (user *UserToken, is bool) { + u, ok := ctx.Get("user") + if !ok { + return nil, false + } + return u.(*UserToken), true +} diff --git a/internal/basic/config/main.go b/internal/basic/config/main.go index 1fef2d4..28a8e8e 100644 --- a/internal/basic/config/main.go +++ b/internal/basic/config/main.go @@ -8,6 +8,7 @@ type Main struct { Http *HttpConf `yaml:"http"` Task *TaskConf `yaml:"task"` Crypto *CryptoConf `yaml:"crypto"` + User *UserConf `yaml:"user"` // 用户配置,配置后接口访问需要登录 } type HttpConf struct { @@ -19,6 +20,10 @@ type TaskConf struct { type CryptoConf struct { Secret string `yaml:"secret"` } +type UserConf struct { + AdminAccount string `yaml:"admin_account"` + AdminPassword string `yaml:"admin_password"` +} var mainConf Main var mainOnce sync.Once diff --git a/internal/server/http.go b/internal/server/http.go index a9bfb2a..67c6595 100644 --- a/internal/server/http.go +++ b/internal/server/http.go @@ -2,8 +2,6 @@ package server import ( "cron/internal/basic/config" - "cron/internal/biz" - "cron/internal/pb" "embed" "github.com/gin-gonic/gin" "html/template" @@ -34,6 +32,8 @@ func InitHttp(Resource embed.FS) *gin.Engine { //r.Static("/static", "web/static") //r.Static("/components", "web/components") + r.Use(UseAuth(nil)) + r.GET("/foundation/dic_gets", routerDicGets) r.GET("/config/list", httpList) r.POST("/config/set", httpSet) @@ -63,64 +63,3 @@ func InitHttp(Resource embed.FS) *gin.Engine { return r } - -// 查看已注册任务 -func httpRegister(ctx *gin.Context) { - rep, err := biz.NewCronConfigService().RegisterList(ctx.Request.Context(), nil) - NewReply(ctx).SetReply(rep, err).RenderJson() -} - -// 任务列表 -func httpList(ctx *gin.Context) { - r := &pb.CronConfigListRequest{} - if err := ctx.BindQuery(r); err != nil { - NewReply(ctx).SetError(pb.ParamError, err.Error()).RenderJson() - return - } - rep, err := biz.NewCronConfigService().List(ctx.Request.Context(), r) - NewReply(ctx).SetReply(rep, err).RenderJson() -} - -// 任务设置 -func httpSet(ctx *gin.Context) { - r := &pb.CronConfigSetRequest{} - if err := ctx.BindJSON(r); err != nil { - NewReply(ctx).SetError(pb.ParamError, err.Error()).RenderJson() - return - } - rep, err := biz.NewCronConfigService().Set(ctx.Request.Context(), r) - NewReply(ctx).SetReply(rep, err).RenderJson() -} - -// 任务状态变更 -func httpChangeStatus(ctx *gin.Context) { - r := &pb.CronConfigSetRequest{} - if err := ctx.BindJSON(r); err != nil { - NewReply(ctx).SetError(pb.ParamError, err.Error()).RenderJson() - return - } - rep, err := biz.NewCronConfigService().ChangeStatus(ctx.Request.Context(), r) - NewReply(ctx).SetReply(rep, err).RenderJson() -} - -// 任务状态变更 -func httpLogByConfig(ctx *gin.Context) { - r := &pb.CronLogByConfigRequest{} - if err := ctx.BindQuery(r); err != nil { - NewReply(ctx).SetError(pb.ParamError, err.Error()).RenderJson() - return - } - rep, err := biz.NewCronLogService().ByConfig(ctx.Request.Context(), r) - NewReply(ctx).SetReply(rep, err).RenderJson() -} - -// 删除日志 -func httpLogDel(ctx *gin.Context) { - r := &pb.CronLogDelRequest{} - if err := ctx.BindJSON(r); err != nil { - NewReply(ctx).SetError(pb.ParamError, err.Error()).RenderJson() - return - } - rep, err := biz.NewCronLogService().Del(ctx.Request.Context(), r) - NewReply(ctx).SetReply(rep, err).RenderJson() -} diff --git a/internal/server/http_middleware.go b/internal/server/http_middleware.go new file mode 100644 index 0000000..944486c --- /dev/null +++ b/internal/server/http_middleware.go @@ -0,0 +1,50 @@ +package server + +import ( + "cron/internal/basic/auth" + "github.com/gin-gonic/gin" + "net/http" +) + +// CORS跨域 +func useCors() gin.HandlerFunc { + return func(ctx *gin.Context) { + ctx.Header("Access-Control-Allow-Origin", "*") + ctx.Header("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE") + ctx.Header("Access-Control-Allow-Headers", "X-Custom-Header,Content-Type,Authorization") + ctx.Header("Access-Control-Expose-Headers", "Content-Disposition,Trace-Id") // 解决跨域自定义头获取 + // 放行所有的options请求 + if ctx.Request.Method == "OPTIONS" { + ctx.AbortWithStatus(http.StatusOK) + } else { + ctx.Next() + } + } +} + +// 授权中间件 +// @param perms +func UseAuth(NotUserRote map[string]string) gin.HandlerFunc { + return func(ctx *gin.Context) { + path := ctx.FullPath() + + if _, ok := NotUserRote[path]; !ok { + user, err := auth.ParseHttpToken(ctx) + if err != nil { + authFailed(ctx.Writer, err.Error()) + //rep.NewResult(ctx).SetErr(err).RenderJson() + ctx.Abort() // 终止 + return + } + ctx.Set("user", user) + } + + ctx.Next() + } +} + +/*认证失败*/ +func authFailed(w http.ResponseWriter, msg string) { + w.Header().Set("WWW-Authenticate", `Basic realm="My METRICS"`) + http.Error(w, msg, http.StatusUnauthorized) +} diff --git a/internal/server/router_config.go b/internal/server/router_config.go new file mode 100644 index 0000000..dfedae8 --- /dev/null +++ b/internal/server/router_config.go @@ -0,0 +1,46 @@ +package server + +import ( + "cron/internal/biz" + "cron/internal/pb" + "github.com/gin-gonic/gin" +) + +// 查看已注册任务 +func httpRegister(ctx *gin.Context) { + rep, err := biz.NewCronConfigService().RegisterList(ctx.Request.Context(), nil) + NewReply(ctx).SetReply(rep, err).RenderJson() +} + +// 任务列表 +func httpList(ctx *gin.Context) { + r := &pb.CronConfigListRequest{} + if err := ctx.BindQuery(r); err != nil { + NewReply(ctx).SetError(pb.ParamError, err.Error()).RenderJson() + return + } + rep, err := biz.NewCronConfigService().List(ctx.Request.Context(), r) + NewReply(ctx).SetReply(rep, err).RenderJson() +} + +// 任务设置 +func httpSet(ctx *gin.Context) { + r := &pb.CronConfigSetRequest{} + if err := ctx.BindJSON(r); err != nil { + NewReply(ctx).SetError(pb.ParamError, err.Error()).RenderJson() + return + } + rep, err := biz.NewCronConfigService().Set(ctx.Request.Context(), r) + NewReply(ctx).SetReply(rep, err).RenderJson() +} + +// 任务状态变更 +func httpChangeStatus(ctx *gin.Context) { + r := &pb.CronConfigSetRequest{} + if err := ctx.BindJSON(r); err != nil { + NewReply(ctx).SetError(pb.ParamError, err.Error()).RenderJson() + return + } + rep, err := biz.NewCronConfigService().ChangeStatus(ctx.Request.Context(), r) + NewReply(ctx).SetReply(rep, err).RenderJson() +} diff --git a/internal/server/router_log.go b/internal/server/router_log.go new file mode 100644 index 0000000..1a87f33 --- /dev/null +++ b/internal/server/router_log.go @@ -0,0 +1,29 @@ +package server + +import ( + "cron/internal/biz" + "cron/internal/pb" + "github.com/gin-gonic/gin" +) + +// 任务状态变更 +func httpLogByConfig(ctx *gin.Context) { + r := &pb.CronLogByConfigRequest{} + if err := ctx.BindQuery(r); err != nil { + NewReply(ctx).SetError(pb.ParamError, err.Error()).RenderJson() + return + } + rep, err := biz.NewCronLogService().ByConfig(ctx.Request.Context(), r) + NewReply(ctx).SetReply(rep, err).RenderJson() +} + +// 删除日志 +func httpLogDel(ctx *gin.Context) { + r := &pb.CronLogDelRequest{} + if err := ctx.BindJSON(r); err != nil { + NewReply(ctx).SetError(pb.ParamError, err.Error()).RenderJson() + return + } + rep, err := biz.NewCronLogService().Del(ctx.Request.Context(), r) + NewReply(ctx).SetReply(rep, err).RenderJson() +} -- Gitee