feat: add middlewares
This commit is contained in:
@@ -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"},
|
||||
|
||||
@@ -3,6 +3,7 @@ Mode = "development"
|
||||
|
||||
[Http]
|
||||
Port = 9800
|
||||
BaseURI = "https://qvyun.mp.jdwan.com"
|
||||
|
||||
[Swagger]
|
||||
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
|
||||
|
||||
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("/")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user