diff --git a/cmd/dashboard/controller/api_v1.go b/cmd/dashboard/controller/api_v1.go index be2d1d5862..83e0bd339c 100644 --- a/cmd/dashboard/controller/api_v1.go +++ b/cmd/dashboard/controller/api_v1.go @@ -31,13 +31,16 @@ func (v *apiV1) serve() { // 不强制认证的 API mr := v.r.Group("monitor") mr.Use(mygin.Authorize(mygin.AuthorizeOption{ - MemberOnly: false, - IsPage: false, - ValidateViewPassword: true, - AllowAPI: true, - Msg: "访问此接口需要认证", - Btn: "点此登录", - Redirect: "/login", + MemberOnly: false, + IsPage: false, + AllowAPI: true, + Msg: "访问此接口需要认证", + Btn: "点此登录", + Redirect: "/login", + })) + mr.Use(mygin.ValidateViewPassword(mygin.ValidateViewPasswordOption{ + IsPage: false, + AbortWhenFail: true, })) mr.GET("/:id", v.monitorHistoriesById) } diff --git a/cmd/dashboard/controller/common_page.go b/cmd/dashboard/controller/common_page.go index cf0b9a1519..a6c94a8c51 100644 --- a/cmd/dashboard/controller/common_page.go +++ b/cmd/dashboard/controller/common_page.go @@ -43,12 +43,14 @@ type commonPage struct { func (cp *commonPage) serve() { cr := cp.r.Group("") - cr.Use(mygin.Authorize(mygin.AuthorizeOption{ - ValidateViewPassword: true, - })) + cr.Use(mygin.Authorize(mygin.AuthorizeOption{})) cr.Use(mygin.PreferredTheme) - cr.GET("/terminal/:id", cp.terminal) cr.POST("/view-password", cp.issueViewPassword) + cr.GET("/terminal/:id", cp.terminal) + cr.Use(mygin.ValidateViewPassword(mygin.ValidateViewPasswordOption{ + IsPage: true, + AbortWhenFail: true, + })) cr.GET("/", cp.home) cr.GET("/service", cp.service) // TODO: 界面直接跳转使用该接口 @@ -65,6 +67,7 @@ type viewPasswordForm struct { func (p *commonPage) issueViewPassword(c *gin.Context) { var vpf viewPasswordForm err := c.ShouldBind(&vpf) + log.Println("bingo", vpf) var hash []byte if err == nil && vpf.Password != singleton.Conf.Site.ViewPassword { err = errors.New(singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "WrongAccessPassword"})) diff --git a/pkg/mygin/auth.go b/pkg/mygin/auth.go index 9549a0f411..a019c8a150 100644 --- a/pkg/mygin/auth.go +++ b/pkg/mygin/auth.go @@ -6,22 +6,19 @@ import ( "time" "github.com/gin-gonic/gin" - "github.com/nicksnyder/go-i18n/v2/i18n" - "golang.org/x/crypto/bcrypt" "github.com/naiba/nezha/model" "github.com/naiba/nezha/service/singleton" ) type AuthorizeOption struct { - GuestOnly bool - MemberOnly bool - ValidateViewPassword bool - IsPage bool - AllowAPI bool - Msg string - Redirect string - Btn string + GuestOnly bool + MemberOnly bool + IsPage bool + AllowAPI bool + Msg string + Redirect string + Btn string } func Authorize(opt AuthorizeOption) func(*gin.Context) { @@ -82,20 +79,5 @@ func Authorize(opt AuthorizeOption) func(*gin.Context) { ShowErrorPage(c, commonErr, opt.IsPage) return } - - // 验证查看密码 - if opt.ValidateViewPassword && singleton.Conf.Site.ViewPassword != "" { - viewPassword, _ := c.Cookie(singleton.Conf.Site.CookieName + "-vp") - if err := bcrypt.CompareHashAndPassword([]byte(viewPassword), []byte(singleton.Conf.Site.ViewPassword)); err != nil { - c.HTML(http.StatusOK, GetPreferredTheme(c, "/viewpassword"), CommonEnvironment(c, gin.H{ - "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "VerifyPassword"}), - "CustomCode": singleton.Conf.Site.CustomCode, - })) - c.Abort() - return - } - - c.Set(model.CtxKeyViewPasswordVerified, true) - } } } diff --git a/pkg/mygin/view_password.go b/pkg/mygin/view_password.go new file mode 100644 index 0000000000..35e406b3f5 --- /dev/null +++ b/pkg/mygin/view_password.go @@ -0,0 +1,52 @@ +package mygin + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/naiba/nezha/model" + "github.com/naiba/nezha/service/singleton" + "github.com/nicksnyder/go-i18n/v2/i18n" + "golang.org/x/crypto/bcrypt" +) + +type ValidateViewPasswordOption struct { + IsPage bool + AbortWhenFail bool +} + +func ValidateViewPassword(opt ValidateViewPasswordOption) gin.HandlerFunc { + return func(c *gin.Context) { + if singleton.Conf.Site.ViewPassword == "" { + return + } + _, authorized := c.Get(model.CtxKeyAuthorizedUser) + if authorized { + return + } + viewPassword, err := c.Cookie(singleton.Conf.Site.CookieName + "-vp") + if err == nil { + err = bcrypt.CompareHashAndPassword([]byte(viewPassword), []byte(singleton.Conf.Site.ViewPassword)) + } + if err == nil { + c.Set(model.CtxKeyViewPasswordVerified, true) + return + } + if !opt.AbortWhenFail { + return + } + if opt.IsPage { + c.HTML(http.StatusOK, GetPreferredTheme(c, "/viewpassword"), CommonEnvironment(c, gin.H{ + "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "VerifyPassword"}), + "CustomCode": singleton.Conf.Site.CustomCode, + })) + + } else { + c.JSON(http.StatusOK, model.Response{ + Code: http.StatusForbidden, + Message: "访问受限", + }) + } + c.Abort() + } +}