servicecontext.go 3.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package svc
  2. import (
  3. "perms-system-server/internal/config"
  4. "perms-system-server/internal/loaders"
  5. "perms-system-server/internal/middleware"
  6. "perms-system-server/internal/model"
  7. "github.com/zeromicro/go-zero/core/limit"
  8. "github.com/zeromicro/go-zero/core/stores/redis"
  9. "github.com/zeromicro/go-zero/core/stores/sqlx"
  10. "github.com/zeromicro/go-zero/rest"
  11. )
  12. type ServiceContext struct {
  13. Config config.Config
  14. JwtAuth rest.Middleware
  15. ProductLoginRateLimit rest.Middleware
  16. AdminLoginRateLimit rest.Middleware
  17. SyncRateLimit rest.Middleware
  18. RefreshTokenRateLimit rest.Middleware
  19. GrpcLoginLimiter *limit.PeriodLimit
  20. GrpcRefreshLimiter *limit.PeriodLimit
  21. GrpcVerifyLimiter *limit.PeriodLimit
  22. GrpcSyncLimiter *limit.PeriodLimit
  23. GrpcGetUserPermsLimiter *limit.PeriodLimit
  24. UsernameLoginLimit *limit.PeriodLimit
  25. TokenOpLimiter *limit.PeriodLimit
  26. UserDetailsLoader *loaders.UserDetailsLoader
  27. Redis *redis.Redis
  28. *model.Models
  29. }
  30. func NewServiceContext(c config.Config) *ServiceContext {
  31. conn := sqlx.NewMysql(c.MySQL.DataSource)
  32. rds := redis.MustNewRedis(c.CacheRedis.Nodes[0].RedisConf)
  33. models := model.NewModels(conn, c.CacheRedis.Nodes, c.CacheRedis.KeyPrefix)
  34. udLoader := loaders.NewUserDetailsLoader(rds, c.CacheRedis.KeyPrefix, models)
  35. productLoginRL := middleware.NewProductLoginRateLimitMiddleware(rds, c.CacheRedis.KeyPrefix, c.BehindProxy)
  36. adminLoginRL := middleware.NewAdminLoginRateLimitMiddleware(rds, c.CacheRedis.KeyPrefix, c.BehindProxy)
  37. syncRlMiddleware := middleware.NewSyncRateLimitMiddleware(rds, c.CacheRedis.KeyPrefix, c.BehindProxy)
  38. refreshTokenRL := middleware.NewRefreshTokenRateLimitMiddleware(rds, c.CacheRedis.KeyPrefix, c.BehindProxy)
  39. grpcLimiter := limit.NewPeriodLimit(60, 20, rds, c.CacheRedis.KeyPrefix+":rl:grpc:login")
  40. // gRPC refreshToken 一般低频操作(分钟级),限紧一点可以同时防签名爆破与并发刷新被用作会话劫持的放大器。
  41. grpcRefreshLimiter := limit.NewPeriodLimit(60, 30, rds, c.CacheRedis.KeyPrefix+":rl:grpc:refresh")
  42. // gRPC verifyToken 是下游每请求都会调用的热路径,阈值必须足够高;这里的作用是兜底防止下游被攻破后把权限中心当 token oracle 爆破。
  43. grpcVerifyLimiter := limit.NewPeriodLimit(60, 6000, rds, c.CacheRedis.KeyPrefix+":rl:grpc:verify")
  44. // 审计 M-R11-1:gRPC SyncPermissions / GetUserPerms 原来没有入口限流,而 HTTP 侧 /api/perm/sync
  45. // 已经挂 SyncRateLimit。限流 key 走 appKey 维度,避免按 IP 把"同一产品不同后端实例共享 egress"
  46. // 整组误伤。桶位按单产品实际节奏给出:单产品每分钟 60 次同步足以覆盖多实例并发发版的真实用量,
  47. // GetUserPerms 1000 次/分钟/产品覆盖多实例冷启动预热峰值,而 appSecret 泄露时能把放大系数压回
  48. // 可控量级。
  49. grpcSyncLimiter := limit.NewPeriodLimit(60, 60, rds, c.CacheRedis.KeyPrefix+":rl:grpc:sync")
  50. grpcGetUserPermsLimiter := limit.NewPeriodLimit(60, 1000, rds, c.CacheRedis.KeyPrefix+":rl:grpc:perms")
  51. usernameLimiter := limit.NewPeriodLimit(300, 10, rds, c.CacheRedis.KeyPrefix+":rl:user")
  52. tokenOpLimiter := limit.NewPeriodLimit(60, 10, rds, c.CacheRedis.KeyPrefix+":rl:tokenop")
  53. return &ServiceContext{
  54. Config: c,
  55. JwtAuth: middleware.NewJwtAuthMiddleware(c.Auth.AccessSecret, udLoader).Handle,
  56. ProductLoginRateLimit: productLoginRL.Handle,
  57. AdminLoginRateLimit: adminLoginRL.Handle,
  58. SyncRateLimit: syncRlMiddleware.Handle,
  59. RefreshTokenRateLimit: refreshTokenRL.Handle,
  60. GrpcLoginLimiter: grpcLimiter,
  61. GrpcRefreshLimiter: grpcRefreshLimiter,
  62. GrpcVerifyLimiter: grpcVerifyLimiter,
  63. GrpcSyncLimiter: grpcSyncLimiter,
  64. GrpcGetUserPermsLimiter: grpcGetUserPermsLimiter,
  65. UsernameLoginLimit: usernameLimiter,
  66. TokenOpLimiter: tokenOpLimiter,
  67. UserDetailsLoader: udLoader,
  68. Redis: rds,
  69. Models: models,
  70. }
  71. }