diff --git a/backend/common/service/http/http.go b/backend/common/service/http/http.go index 35fe628..a24b26c 100644 --- a/backend/common/service/http/http.go +++ b/backend/common/service/http/http.go @@ -61,9 +61,9 @@ type Http struct { func Serve(cmd *cobra.Command, args []string) error { return container.Container.Invoke(func(http Http) error { mid := http.Middlewares - http.Service.Engine.Use(mid.Verify) + http.Service.Engine.Use(mid.WeChatVerify) http.Service.Engine.Use(mid.AuthUserInfo) - http.Service.Engine.Use(mid.SilentAuth) + http.Service.Engine.Use(mid.WeChatSilentAuth) mounts := map[string][]string{ "/t/{tenant}": {"users", "medias"}, diff --git a/backend/config.toml b/backend/config.toml index fb38b60..1a4f501 100755 --- a/backend/config.toml +++ b/backend/config.toml @@ -3,6 +3,7 @@ Mode = "development" [Http] Port = 9800 +BaseURI = "https://qvyun.mp.jdwan.com" [Swagger] BaseRoute = "doc" diff --git a/backend/modules/middlewares/m_jwt_parse.go b/backend/modules/middlewares/m_jwt_parse.go new file mode 100644 index 0000000..3337a21 --- /dev/null +++ b/backend/modules/middlewares/m_jwt_parse.go @@ -0,0 +1,34 @@ +package middlewares + +import ( + "context" + + "backend/common/consts" + + "github.com/gofiber/fiber/v3" + "github.com/pkg/errors" +) + +func (f *Middlewares) JwtParse(c fiber.Ctx) error { + tokens := c.GetReqHeaders()["Authorization"] + if len(tokens) == 0 { + return c.Next() + } + + token := tokens[0] + claim, err := f.jwt.Parse(token) + if err != nil { + return errors.Wrap(err, "failed to parse token") + } + + // query user + user, err := f.userSvc.GetByOpenID(c.Context(), claim.ID) + if err != nil { + return errors.Wrap(err, "failed to get user") + } + + c.SetUserContext(context.WithValue(c.UserContext(), consts.CtxKeyJwt, token)) + c.SetUserContext(context.WithValue(c.UserContext(), consts.CtxKeySession, user)) + + return c.Next() +} diff --git a/backend/modules/middlewares/m_wechat_silent_auth.go b/backend/modules/middlewares/m_wechat_silent_auth.go new file mode 100644 index 0000000..d4857c9 --- /dev/null +++ b/backend/modules/middlewares/m_wechat_silent_auth.go @@ -0,0 +1,33 @@ +package middlewares + +import ( + "backend/providers/wechat" + + "github.com/gofiber/fiber/v3" + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" +) + +func (f *Middlewares) WeChatSilentAuth(c fiber.Ctx) error { + // if cookie not exists key "openid", then redirect to the wechat auth page + token := c.GetReqHeaders()["Authorization"] + if len(token) != 0 { + return c.Next() + } + + // get current full url + url := c.BaseURL() + url = "https://qvyun.mp.jdwan.com" + log.WithField("module", "middleware.SilentAuth").Debug("url:", url) + + to, err := f.client.ScopeAuthorizeURL( + wechat.ScopeAuthorizeURLWithRedirectURI(url), + wechat.ScopeAuthorizeURLWithState("sns_basic_auth"), + ) + if err != nil { + return errors.Wrap(err, "failed to get wechat auth url") + } + log.WithField("module", "middleware.SilentAuth").Debug("redirectTo: ", to.String()) + + return c.Redirect().To(to.String()) +} diff --git a/backend/modules/middlewares/m_wechat_verify.go b/backend/modules/middlewares/m_wechat_verify.go new file mode 100644 index 0000000..8ca155d --- /dev/null +++ b/backend/modules/middlewares/m_wechat_verify.go @@ -0,0 +1,33 @@ +package middlewares + +import ( + "github.com/gofiber/fiber/v3" + log "github.com/sirupsen/logrus" +) + +// 此方法用于微信首次接入时的数据验证 +func (f *Middlewares) WeChatVerify(c fiber.Ctx) error { + // get the query parameters + signature := c.Query("signature") + timestamp := c.Query("timestamp") + nonce := c.Query("nonce") + echostr := c.Query("echostr") + + if signature == "" || timestamp == "" || nonce == "" || echostr == "" { + return c.Next() + } + + log.WithField("method", "Verify").WithFields(log.Fields{ + "signature": signature, + "timestamp": timestamp, + "nonce": nonce, + "echostr": echostr, + }).Debug("begin verify signature") + + // verify the signature + if err := f.client.Verify(signature, timestamp, nonce); err != nil { + return c.SendString(err.Error()) + } + + return c.SendString(echostr) +} diff --git a/backend/modules/middlewares/mid_auth_userinfo.go b/backend/modules/middlewares/mid_auth_userinfo.go new file mode 100644 index 0000000..40d5259 --- /dev/null +++ b/backend/modules/middlewares/mid_auth_userinfo.go @@ -0,0 +1,54 @@ +package middlewares + +import ( + "backend/pkg/pg" + "backend/providers/jwt" + + "github.com/gofiber/fiber/v3" + "github.com/jinzhu/copier" + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" +) + +func (f *Middlewares) AuthUserInfo(c fiber.Ctx) error { + state := c.Query("state") + code := c.Query("code") + + if state == "" && code == "" { + return c.Next() + } + + if state != "sns_basic_auth" { + return c.Next() + } + log.WithField("module", "middleware.AuthUserInfo").Debug("code", code) + + // get the openid + token, err := f.client.AuthorizeCode2Token(code) + if err != nil { + return errors.Wrap(err, "failed to get openid") + } + + var oauthInfo pg.UserOAuth + copier.Copy(&oauthInfo, token) + user, err := f.userSvc.GetOrNew(c.Context(), 1, token.Openid, oauthInfo) + if err != nil { + return errors.Wrap(err, "failed to get user") + } + + claim := f.jwt.CreateClaims(jwt.BaseClaims{UID: uint64(user.ID)}) + claim.ID = user.OpenID + jwtToken, err := f.jwt.CreateToken(claim) + if err != nil { + return errors.Wrap(err, "failed to create token") + } + + // set the openid to the cookie + c.Cookie(&fiber.Cookie{ + Name: "token", + Value: jwtToken, + HTTPOnly: true, + }) + + return c.Redirect().To("/") +} diff --git a/backend/modules/middlewares/mid_debug.go b/backend/modules/middlewares/mid_debug.go new file mode 100644 index 0000000..ecb33af --- /dev/null +++ b/backend/modules/middlewares/mid_debug.go @@ -0,0 +1,9 @@ +package middlewares + +import ( + "github.com/gofiber/fiber/v3" +) + +func (f *Middlewares) DebugMode(c fiber.Ctx) error { + return c.Next() +} diff --git a/backend/modules/middlewares/middlewares.go b/backend/modules/middlewares/middlewares.go index 17c3487..8f3fc5c 100644 --- a/backend/modules/middlewares/middlewares.go +++ b/backend/modules/middlewares/middlewares.go @@ -1,17 +1,10 @@ package middlewares import ( - "context" - - "backend/common/consts" "backend/modules/users" - "backend/pkg/pg" "backend/providers/jwt" "backend/providers/wechat" - "github.com/gofiber/fiber/v3" - "github.com/jinzhu/copier" - "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) @@ -27,110 +20,3 @@ func (f *Middlewares) Prepare() error { f.log = log.WithField("module", "middleware") return nil } - -func (f *Middlewares) Verify(c fiber.Ctx) error { - // get the query parameters - signature := c.Query("signature") - timestamp := c.Query("timestamp") - nonce := c.Query("nonce") - echostr := c.Query("echostr") - - if signature == "" || timestamp == "" || nonce == "" || echostr == "" { - return c.Next() - } - - log.WithField("method", "Verify").WithFields(log.Fields{ - "signature": signature, - "timestamp": timestamp, - "nonce": nonce, - "echostr": echostr, - }).Debug("begin verify signature") - - // verify the signature - if err := f.client.Verify(signature, timestamp, nonce); err != nil { - return c.SendString(err.Error()) - } - - return c.SendString(echostr) -} - -func (f *Middlewares) SilentAuth(c fiber.Ctx) error { - // if cookie not exists key "openid", then redirect to the wechat auth page - tokenCookie := c.Cookies("token", "") - if tokenCookie != "" { - claim, err := f.jwt.Parse(tokenCookie) - if err != nil { - return errors.Wrap(err, "failed to parse token") - } - - // query user - user, err := f.userSvc.GetByOpenID(c.Context(), claim.ID) - if err != nil { - return errors.Wrap(err, "failed to get user") - } - - c.SetUserContext(context.WithValue(c.UserContext(), consts.CtxKeyJwt, tokenCookie)) - c.SetUserContext(context.WithValue(c.UserContext(), consts.CtxKeySession, user)) - - return c.Next() - } - - // get current full url - url := c.BaseURL() - url = "https://qvyun.mp.jdwan.com" - log.WithField("module", "middleware.SilentAuth").Debug("url:", url) - - to, err := f.client.ScopeAuthorizeURL( - wechat.ScopeAuthorizeURLWithRedirectURI(url), - wechat.ScopeAuthorizeURLWithState("sns_basic_auth"), - ) - if err != nil { - return errors.Wrap(err, "failed to get wechat auth url") - } - log.WithField("module", "middleware.SilentAuth").Debug("redirectTo: ", to.String()) - - return c.Redirect().To(to.String()) -} - -func (f *Middlewares) AuthUserInfo(c fiber.Ctx) error { - state := c.Query("state") - code := c.Query("code") - - if state == "" && code == "" { - return c.Next() - } - - if state != "sns_basic_auth" { - return c.Next() - } - log.WithField("module", "middleware.AuthUserInfo").Debug("code", code) - - // get the openid - token, err := f.client.AuthorizeCode2Token(code) - if err != nil { - return errors.Wrap(err, "failed to get openid") - } - - var oauthInfo pg.UserOAuth - copier.Copy(&oauthInfo, token) - user, err := f.userSvc.GetOrNew(c.Context(), 1, token.Openid, oauthInfo) - if err != nil { - return errors.Wrap(err, "failed to get user") - } - - claim := f.jwt.CreateClaims(jwt.BaseClaims{UID: uint64(user.ID)}) - claim.ID = user.OpenID - jwtToken, err := f.jwt.CreateToken(claim) - if err != nil { - return errors.Wrap(err, "failed to create token") - } - - // set the openid to the cookie - c.Cookie(&fiber.Cookie{ - Name: "token", - Value: jwtToken, - HTTPOnly: true, - }) - - return c.Redirect().To("/") -} diff --git a/backend/providers/http/config.go b/backend/providers/http/config.go index 8ad99c5..611f210 100644 --- a/backend/providers/http/config.go +++ b/backend/providers/http/config.go @@ -9,7 +9,7 @@ const DefaultPrefix = "Http" type Config struct { StaticPath *string StaticRoute *string - Host *string + BaseURI *string Port uint Tls *Tls Cors *Cors @@ -34,12 +34,5 @@ type Whitelist struct { } func (h *Config) Address() string { - if h.Host == nil { - return h.PortString() - } - return fmt.Sprintf("%s:%d", *h.Host, h.Port) -} - -func (h *Config) PortString() string { return fmt.Sprintf(":%d", h.Port) } diff --git a/backend/providers/http/engine.go b/backend/providers/http/engine.go index 598969b..a5763aa 100644 --- a/backend/providers/http/engine.go +++ b/backend/providers/http/engine.go @@ -38,6 +38,7 @@ func (svc *Service) Serve() error { OnShutdownError: func(err error) { log.Error("http server shutdown error: ", err) }, + // DisableStartupMessage: true, } @@ -52,7 +53,7 @@ func (svc *Service) Serve() error { svc.Engine.Shutdown() }) - return svc.Engine.Listen(svc.conf.PortString(), listenConfig) + return svc.Engine.Listen(svc.conf.Address(), listenConfig) } func Provide(opts ...opt.Option) error {