middleware.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. package permlib
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "net/http"
  7. "strings"
  8. )
  9. func (e *Engine) authMiddleware(next http.HandlerFunc) http.HandlerFunc {
  10. return func(w http.ResponseWriter, req *http.Request) {
  11. authHeader := req.Header.Get("Authorization")
  12. if authHeader == "" {
  13. e.cfg.Callbacks.OnError(w, req, 401, 401, "未登录")
  14. return
  15. }
  16. tokenStr := strings.TrimPrefix(authHeader, "Bearer ")
  17. if tokenStr == authHeader {
  18. e.cfg.Callbacks.OnError(w, req, 401, 401, "token格式错误")
  19. return
  20. }
  21. info, err := e.verifyAndGetUser(req.Context(), tokenStr)
  22. if err != nil {
  23. e.cfg.Callbacks.OnError(w, req, 401, 401, "token无效或已过期")
  24. return
  25. }
  26. apiCode := e.resolvePermCode(req)
  27. if apiCode != "" && !containsPerm(info.Perms, apiCode) {
  28. e.cfg.Callbacks.OnError(w, req, 403, 403, fmt.Sprintf("无权访问: %s", apiCode))
  29. return
  30. }
  31. user := &UserInfo{
  32. UserId: info.UserId,
  33. Username: info.Username,
  34. ProductCode: info.ProductCode,
  35. MemberType: info.MemberType,
  36. Perms: info.Perms,
  37. }
  38. ctx := withUser(req.Context(), user)
  39. req, rejected := e.filterRequest(req, info.Perms)
  40. if rejected {
  41. e.cfg.Callbacks.OnError(w, req, 403, 403, "包含无权写入的字段")
  42. return
  43. }
  44. dataCode := e.resolveDataCode(req, apiCode)
  45. hasDataPerm := dataCode == "" || containsPerm(info.Perms, dataCode)
  46. var wrappedNext http.HandlerFunc
  47. if e.hasRespFilter(req) {
  48. wrappedNext = func(w http.ResponseWriter, req *http.Request) {
  49. rw := newFilterResponseWriter(w, req, info.Perms, e)
  50. next(rw, req)
  51. rw.flush()
  52. }
  53. } else {
  54. wrappedNext = next
  55. }
  56. e.cfg.Callbacks.OnSuccess(w, req.WithContext(ctx), wrappedNext, user, hasDataPerm)
  57. }
  58. }
  59. func (e *Engine) resolvePermCode(req *http.Request) string {
  60. key := req.Method + " " + req.URL.Path
  61. if decl, ok := e.routePerms[key]; ok {
  62. return decl.PermCode
  63. }
  64. return ""
  65. }
  66. func (e *Engine) resolveDataCode(req *http.Request, apiCode string) string {
  67. key := req.Method + " " + req.URL.Path
  68. if decl, ok := e.routePerms[key]; ok {
  69. return decl.DataCode
  70. }
  71. if apiCode != "" {
  72. return apiToDataCode(apiCode)
  73. }
  74. return ""
  75. }
  76. func (e *Engine) hasRespFilter(req *http.Request) bool {
  77. key := req.Method + " " + req.URL.Path
  78. if fm, ok := e.fieldPerms[key]; ok {
  79. return len(fm.Response) > 0
  80. }
  81. return false
  82. }
  83. func (e *Engine) filterRequest(req *http.Request, perms []string) (*http.Request, bool) {
  84. key := req.Method + " " + req.URL.Path
  85. if fm, ok := e.fieldPerms[key]; ok && len(fm.Request) > 0 {
  86. return filterRequestByMap(req, fm.Request, perms, e.cfg.FieldWriteMode)
  87. }
  88. return req, false
  89. }
  90. func (e *Engine) verifyAndGetUser(ctx context.Context, token string) (*cachedUser, error) {
  91. if u, ok := e.cache.get(token); ok {
  92. return u, nil
  93. }
  94. v, err, _ := e.cache.sf.Do(token, func() (interface{}, error) {
  95. resp, err := e.client.verifyToken(ctx, token)
  96. if err != nil {
  97. return nil, err
  98. }
  99. if !resp.Valid {
  100. return nil, fmt.Errorf("token验证失败")
  101. }
  102. u := &cachedUser{
  103. UserId: resp.UserId,
  104. Username: resp.Username,
  105. ProductCode: resp.ProductCode,
  106. MemberType: resp.MemberType,
  107. Perms: resp.Perms,
  108. }
  109. e.cache.set(token, u)
  110. return u, nil
  111. })
  112. if err != nil {
  113. return nil, err
  114. }
  115. return v.(*cachedUser), nil
  116. }
  117. func containsPerm(perms []string, code string) bool {
  118. for _, p := range perms {
  119. if p == code {
  120. return true
  121. }
  122. }
  123. return false
  124. }
  125. func filterRequestByMap(req *http.Request, fieldMap map[string]string, perms []string, mode FieldWriteMode) (*http.Request, bool) {
  126. if req.Body == nil {
  127. return req, false
  128. }
  129. body, err := readBody(req)
  130. if err != nil || len(body) == 0 {
  131. return req, false
  132. }
  133. var obj map[string]json.RawMessage
  134. if err := json.Unmarshal(body, &obj); err != nil {
  135. restoreBody(req, body)
  136. return req, false
  137. }
  138. permSet := toPermSet(perms)
  139. for jsonField, permCode := range fieldMap {
  140. if _, has := obj[jsonField]; has && !permSet[permCode] {
  141. if mode == FieldWriteReject {
  142. restoreBody(req, body)
  143. return req, true
  144. }
  145. delete(obj, jsonField)
  146. }
  147. }
  148. filtered, _ := json.Marshal(obj)
  149. restoreBody(req, filtered)
  150. req.ContentLength = int64(len(filtered))
  151. return req, false
  152. }