feat: add middlewares
This commit is contained in:
@@ -61,9 +61,9 @@ type Http struct {
|
|||||||
func Serve(cmd *cobra.Command, args []string) error {
|
func Serve(cmd *cobra.Command, args []string) error {
|
||||||
return container.Container.Invoke(func(http Http) error {
|
return container.Container.Invoke(func(http Http) error {
|
||||||
mid := http.Middlewares
|
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.AuthUserInfo)
|
||||||
http.Service.Engine.Use(mid.SilentAuth)
|
http.Service.Engine.Use(mid.WeChatSilentAuth)
|
||||||
|
|
||||||
mounts := map[string][]string{
|
mounts := map[string][]string{
|
||||||
"/t/{tenant}": {"users", "medias"},
|
"/t/{tenant}": {"users", "medias"},
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ Mode = "development"
|
|||||||
|
|
||||||
[Http]
|
[Http]
|
||||||
Port = 9800
|
Port = 9800
|
||||||
|
BaseURI = "https://qvyun.mp.jdwan.com"
|
||||||
|
|
||||||
[Swagger]
|
[Swagger]
|
||||||
BaseRoute = "doc"
|
BaseRoute = "doc"
|
||||||
|
|||||||
34
backend/modules/middlewares/m_jwt_parse.go
Normal file
34
backend/modules/middlewares/m_jwt_parse.go
Normal file
@@ -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()
|
||||||
|
}
|
||||||
33
backend/modules/middlewares/m_wechat_silent_auth.go
Normal file
33
backend/modules/middlewares/m_wechat_silent_auth.go
Normal file
@@ -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())
|
||||||
|
}
|
||||||
33
backend/modules/middlewares/m_wechat_verify.go
Normal file
33
backend/modules/middlewares/m_wechat_verify.go
Normal file
@@ -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)
|
||||||
|
}
|
||||||
54
backend/modules/middlewares/mid_auth_userinfo.go
Normal file
54
backend/modules/middlewares/mid_auth_userinfo.go
Normal file
@@ -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("/")
|
||||||
|
}
|
||||||
9
backend/modules/middlewares/mid_debug.go
Normal file
9
backend/modules/middlewares/mid_debug.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package middlewares
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (f *Middlewares) DebugMode(c fiber.Ctx) error {
|
||||||
|
return c.Next()
|
||||||
|
}
|
||||||
@@ -1,17 +1,10 @@
|
|||||||
package middlewares
|
package middlewares
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
|
|
||||||
"backend/common/consts"
|
|
||||||
"backend/modules/users"
|
"backend/modules/users"
|
||||||
"backend/pkg/pg"
|
|
||||||
"backend/providers/jwt"
|
"backend/providers/jwt"
|
||||||
"backend/providers/wechat"
|
"backend/providers/wechat"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v3"
|
|
||||||
"github.com/jinzhu/copier"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -27,110 +20,3 @@ func (f *Middlewares) Prepare() error {
|
|||||||
f.log = log.WithField("module", "middleware")
|
f.log = log.WithField("module", "middleware")
|
||||||
return nil
|
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("/")
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const DefaultPrefix = "Http"
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
StaticPath *string
|
StaticPath *string
|
||||||
StaticRoute *string
|
StaticRoute *string
|
||||||
Host *string
|
BaseURI *string
|
||||||
Port uint
|
Port uint
|
||||||
Tls *Tls
|
Tls *Tls
|
||||||
Cors *Cors
|
Cors *Cors
|
||||||
@@ -34,12 +34,5 @@ type Whitelist struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Config) Address() string {
|
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)
|
return fmt.Sprintf(":%d", h.Port)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ func (svc *Service) Serve() error {
|
|||||||
OnShutdownError: func(err error) {
|
OnShutdownError: func(err error) {
|
||||||
log.Error("http server shutdown error: ", err)
|
log.Error("http server shutdown error: ", err)
|
||||||
},
|
},
|
||||||
|
|
||||||
// DisableStartupMessage: true,
|
// DisableStartupMessage: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +53,7 @@ func (svc *Service) Serve() error {
|
|||||||
svc.Engine.Shutdown()
|
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 {
|
func Provide(opts ...opt.Option) error {
|
||||||
|
|||||||
Reference in New Issue
Block a user