main.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package main
  2. import (
  3. "context"
  4. "encoding/json"
  5. "io"
  6. "log"
  7. "net/http"
  8. "github.com/xiaozi/permlib"
  9. )
  10. type CreateUserReq struct {
  11. Username string `json:"username"`
  12. Email string `json:"email" perm:"data:user:email:write"`
  13. Phone string `json:"phone" perm:"data:user:phone:write"`
  14. }
  15. type UserListResp struct {
  16. ID int64 `json:"id"`
  17. Username string `json:"username"`
  18. Email string `json:"email" perm:"data:user:email:read"`
  19. Phone string `json:"phone" perm:"data:user:phone:read"`
  20. }
  21. func writeJSON(w http.ResponseWriter, status int, body interface{}) {
  22. w.Header().Set("Content-Type", "application/json; charset=utf-8")
  23. w.WriteHeader(status)
  24. json.NewEncoder(w).Encode(body)
  25. }
  26. func main() {
  27. engine, err := permlib.New(permlib.Config{
  28. ProductCode: "crm",
  29. AppKey: "ak_crm",
  30. AppSecret: "sk_crm",
  31. PermServerAddr: "localhost:10002",
  32. FieldWriteMode: permlib.FieldWriteSilent,
  33. Callbacks: permlib.AuthCallbacks{
  34. OnError: func(w http.ResponseWriter, r *http.Request, httpStatus int, code int, msg string) {
  35. writeJSON(w, httpStatus, map[string]interface{}{
  36. "success": false,
  37. "errorCode": code,
  38. "errorMessage": msg,
  39. })
  40. },
  41. OnSuccess: func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc, user *permlib.UserInfo, hasDataPerm bool) {
  42. if !hasDataPerm {
  43. writeJSON(w, http.StatusOK, map[string]interface{}{
  44. "success": true,
  45. "data": map[string]interface{}{},
  46. })
  47. return
  48. }
  49. next(w, r)
  50. },
  51. },
  52. })
  53. if err != nil {
  54. log.Fatal(err)
  55. }
  56. if err := engine.Start(context.Background()); err != nil {
  57. log.Fatal(err)
  58. }
  59. mux := http.NewServeMux()
  60. // 公开接口:产品端自己实现 handler,完全控制响应格式
  61. mux.HandleFunc("POST /api/auth/login", makeLoginHandler(engine))
  62. mux.HandleFunc("POST /api/auth/refreshToken", makeRefreshTokenHandler(engine))
  63. // 鉴权接口:通过 AuthMiddlewareWithOpts 套上鉴权 + 字段过滤
  64. mux.HandleFunc("POST /api/user/create", engine.AuthMiddleware(createUser))
  65. mux.HandleFunc("POST /api/user/list", engine.AuthMiddleware(listUsers))
  66. log.Println("server listening on :8080")
  67. log.Fatal(http.ListenAndServe(":8080", mux))
  68. }
  69. func makeLoginHandler(engine *permlib.Engine) http.HandlerFunc {
  70. return func(w http.ResponseWriter, r *http.Request) {
  71. body, err := io.ReadAll(r.Body)
  72. r.Body.Close()
  73. if err != nil {
  74. writeJSON(w, http.StatusBadRequest, map[string]interface{}{"success": false, "errorMessage": "请求体读取失败"})
  75. return
  76. }
  77. var req struct {
  78. Username string `json:"username"`
  79. Password string `json:"password"`
  80. }
  81. if err := json.Unmarshal(body, &req); err != nil || req.Username == "" || req.Password == "" {
  82. writeJSON(w, http.StatusBadRequest, map[string]interface{}{"success": false, "errorMessage": "用户名和密码不能为空"})
  83. return
  84. }
  85. result, err := engine.Login(r.Context(), req.Username, req.Password)
  86. if err != nil {
  87. writeJSON(w, http.StatusUnauthorized, map[string]interface{}{"success": false, "errorMessage": err.Error()})
  88. return
  89. }
  90. writeJSON(w, http.StatusOK, map[string]interface{}{
  91. "success": true,
  92. "data": map[string]interface{}{
  93. "accessToken": result.AccessToken,
  94. "refreshToken": result.RefreshToken,
  95. "expires": result.Expires,
  96. "userId": result.UserId,
  97. "username": result.Username,
  98. "nickname": result.Nickname,
  99. "memberType": result.MemberType,
  100. "perms": result.Perms,
  101. },
  102. })
  103. }
  104. }
  105. func makeRefreshTokenHandler(engine *permlib.Engine) http.HandlerFunc {
  106. return func(w http.ResponseWriter, r *http.Request) {
  107. body, err := io.ReadAll(r.Body)
  108. r.Body.Close()
  109. if err != nil {
  110. writeJSON(w, http.StatusBadRequest, map[string]interface{}{"success": false, "errorMessage": "请求体读取失败"})
  111. return
  112. }
  113. var req struct {
  114. RefreshToken string `json:"refreshToken"`
  115. }
  116. if err := json.Unmarshal(body, &req); err != nil || req.RefreshToken == "" {
  117. writeJSON(w, http.StatusBadRequest, map[string]interface{}{"success": false, "errorMessage": "refreshToken不能为空"})
  118. return
  119. }
  120. result, err := engine.RefreshToken(r.Context(), req.RefreshToken)
  121. if err != nil {
  122. writeJSON(w, http.StatusUnauthorized, map[string]interface{}{"success": false, "errorMessage": err.Error()})
  123. return
  124. }
  125. writeJSON(w, http.StatusOK, map[string]interface{}{
  126. "success": true,
  127. "data": map[string]interface{}{
  128. "accessToken": result.AccessToken,
  129. "refreshToken": result.RefreshToken,
  130. "expires": result.Expires,
  131. "perms": result.Perms,
  132. },
  133. })
  134. }
  135. }
  136. func createUser(w http.ResponseWriter, r *http.Request) {
  137. user := permlib.GetUser(r.Context())
  138. writeJSON(w, http.StatusOK, map[string]interface{}{
  139. "success": true,
  140. "data": map[string]interface{}{"createdBy": user.Username},
  141. })
  142. }
  143. func listUsers(w http.ResponseWriter, r *http.Request) {
  144. users := []UserListResp{
  145. {ID: 1, Username: "alice", Email: "[email protected]", Phone: "13800001111"},
  146. {ID: 2, Username: "bob", Email: "[email protected]", Phone: "13800002222"},
  147. }
  148. writeJSON(w, http.StatusOK, map[string]interface{}{
  149. "success": true,
  150. "data": users,
  151. })
  152. }