t
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"bd-server/app/main/api/internal/config"
|
||||
"bd-server/app/main/model"
|
||||
jwtx "bd-server/common/jwt"
|
||||
)
|
||||
|
||||
const (
|
||||
HeaderMembershipExpired = "X-Membership-Expired"
|
||||
)
|
||||
|
||||
// MembershipExpiredInterceptor 检测代理会员是否过期,过期则写入响应头
|
||||
// 由于是全局中间件(在 AuthInterceptor 之前执行),需要自己从请求头解析 JWT
|
||||
type MembershipExpiredInterceptor struct {
|
||||
AgentModel model.AgentModel
|
||||
Config config.Config
|
||||
}
|
||||
|
||||
func NewMembershipExpiredInterceptor(agentModel model.AgentModel, c config.Config) *MembershipExpiredInterceptor {
|
||||
return &MembershipExpiredInterceptor{
|
||||
AgentModel: agentModel,
|
||||
Config: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MembershipExpiredInterceptor) Handle(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// 先检测会员过期状态(必须在 next() 之前设置响应头,否则响应已发送 header 无法生效)
|
||||
needNotifyExpired := false
|
||||
|
||||
// 由于全局中间件在路由中间件之前执行,context 中可能没有 claims
|
||||
// 先尝试从 context 获取,如果没有则自己从 Authorization 头解析
|
||||
claims := getClaimsFromContext(r)
|
||||
if claims == nil {
|
||||
claims = parseClaimsFromAuthHeader(r, m.Config.JwtAuth.AccessSecret)
|
||||
}
|
||||
|
||||
if claims != nil && claims.UserType == model.UserTypeNormal && r.URL.Path != "/api/v1/agent/info" {
|
||||
agent, err := m.AgentModel.FindOneByUserId(r.Context(), claims.UserId)
|
||||
if err == nil && agent != nil {
|
||||
// 到期时间已过,说明会员已过期(不管等级是否已降级为 normal)
|
||||
if agent.MembershipExpiryTime.Valid && !agent.MembershipExpiryTime.Time.After(time.Now()) {
|
||||
needNotifyExpired = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 在 next() 之前设置响应头(此时 headers 还没发送给客户端)
|
||||
if needNotifyExpired {
|
||||
w.Header().Set(HeaderMembershipExpired, "true")
|
||||
}
|
||||
|
||||
// 执行业务逻辑
|
||||
next(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func getClaimsFromContext(r *http.Request) *jwtx.JwtClaims {
|
||||
value := r.Context().Value(jwtx.ExtraKey)
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
if claims, ok := value.(*jwtx.JwtClaims); ok {
|
||||
return claims
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseClaimsFromAuthHeader(r *http.Request, secret string) *jwtx.JwtClaims {
|
||||
authHeader := r.Header.Get("Authorization")
|
||||
if authHeader == "" {
|
||||
return nil
|
||||
}
|
||||
claims, err := jwtx.ParseJwtToken(authHeader, secret)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return claims
|
||||
}
|
||||
Reference in New Issue
Block a user