From 9865f7dae9d1f7a837fcc4917ba42c141b211fa2 Mon Sep 17 00:00:00 2001 From: gjs Date: Mon, 10 Aug 2026 18:05:29 +0800 Subject: [PATCH] add Refresh --- README.md | 2 +- admin/admin/admin.pb.go | 67 +++++-- admin/admin/admin_grpc.pb.go | 52 ++++- admin/adminclient/admin.go | 13 +- admin/internal/dao/login.go | 3 +- admin/internal/logic/adminloginlogic.go | 47 +++-- admin/internal/logic/adminrefreshlogic.go | 86 ++++++++ admin/internal/server/adminserver.go | 5 + admin/proto/admin.proto | 9 + bff/etc/admin.pb | Bin 14703 -> 14813 bytes bff/internal/response/user.go | 59 ++++-- deploy/apisix/apisix.yaml | 25 +-- deploy/apisix/lua/auth.lua | 232 ++++++++-------------- pkg/utils/config.go | 3 +- pkg/utils/loginInfo.go | 9 +- pkg/utils/status.go | 23 ++- 16 files changed, 390 insertions(+), 245 deletions(-) create mode 100644 admin/internal/logic/adminrefreshlogic.go diff --git a/README.md b/README.md index 82eab0c..7b5186f 100644 --- a/README.md +++ b/README.md @@ -371,7 +371,7 @@ rpc Ping(Request) returns (Response) { ### 命令 ①:生成服务端 pb / grpc ```bash -protoc -I. -I../pkg/third_party --go_out=. --go-grpc_out=. proto/order.proto +goctl rpc protoc proto/admin.proto --proto_path=. --proto_path=../pkg/third_party --go_out=. --go-grpc_out=. --zrpc_out=. ``` **什么时候跑:** diff --git a/admin/admin/admin.pb.go b/admin/admin/admin.pb.go index 58dc8cf..983c958 100644 --- a/admin/admin/admin.pb.go +++ b/admin/admin/admin.pb.go @@ -510,6 +510,42 @@ func (x *AdminLoginRequest) GetPassword() string { return "" } +type AdminEmptyRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AdminEmptyRequest) Reset() { + *x = AdminEmptyRequest{} + mi := &file_proto_admin_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdminEmptyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdminEmptyRequest) ProtoMessage() {} + +func (x *AdminEmptyRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_admin_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AdminEmptyRequest.ProtoReflect.Descriptor instead. +func (*AdminEmptyRequest) Descriptor() ([]byte, []int) { + return file_proto_admin_proto_rawDescGZIP(), []int{8} +} + var File_proto_admin_proto protoreflect.FileDescriptor const file_proto_admin_proto_rawDesc = "" + @@ -547,7 +583,8 @@ const file_proto_admin_proto_rawDesc = "" + "\x06status\x18\a \x01(\x05R\x06status\"K\n" + "\x11AdminLoginRequest\x12\x1a\n" + "\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" + - "\bpassword\x18\x02 \x01(\tR\bpassword2\xfe\x04\n" + + "\bpassword\x18\x02 \x01(\tR\bpassword\"\x13\n" + + "\x11AdminEmptyRequest2\xd7\x05\n" + "\x05Admin\x12V\n" + "\tAdminEdit\x12\x17.admin.AdminEditRequest\x1a\x0f.admin.Response\"\x1f\x82\xd3\xe4\x93\x02\x19:\x01*\"\x14/admin/v3/admin/edit\x12W\n" + "\vAdminStatus\x12\x14.admin.StatusRequest\x1a\x0f.admin.Response\"!\x82\xd3\xe4\x93\x02\x1b:\x01*\"\x16/admin/v3/admin/status\x12X\n" + @@ -557,7 +594,8 @@ const file_proto_admin_proto_rawDesc = "" + "\n" + "AdminItems\x12\x18.admin.AdminItemsRequest\x1a\x0f.admin.Response\" \x82\xd3\xe4\x93\x02\x1a:\x01*\x12\x15/admin/v3/admin/items\x12S\n" + "\n" + - "AdminLogin\x12\x18.admin.AdminLoginRequest\x1a\x0f.admin.Response\"\x1a\x82\xd3\xe4\x93\x02\x14:\x01*\"\x0f/admin/v3/loginB\tZ\a./adminb\x06proto3" + "AdminLogin\x12\x18.admin.AdminLoginRequest\x1a\x0f.admin.Response\"\x1a\x82\xd3\xe4\x93\x02\x14:\x01*\"\x0f/admin/v3/login\x12W\n" + + "\fAdminRefresh\x12\x18.admin.AdminEmptyRequest\x1a\x0f.admin.Response\"\x1c\x82\xd3\xe4\x93\x02\x16:\x01*\"\x11/admin/v3/refreshB\tZ\a./adminb\x06proto3" var ( file_proto_admin_proto_rawDescOnce sync.Once @@ -571,7 +609,7 @@ func file_proto_admin_proto_rawDescGZIP() []byte { return file_proto_admin_proto_rawDescData } -var file_proto_admin_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_proto_admin_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_proto_admin_proto_goTypes = []any{ (*AdminEditRequest)(nil), // 0: admin.AdminEditRequest (*StatusRequest)(nil), // 1: admin.StatusRequest @@ -581,6 +619,7 @@ var file_proto_admin_proto_goTypes = []any{ (*AdminInfoRequest)(nil), // 5: admin.AdminInfoRequest (*AdminItemsRequest)(nil), // 6: admin.AdminItemsRequest (*AdminLoginRequest)(nil), // 7: admin.AdminLoginRequest + (*AdminEmptyRequest)(nil), // 8: admin.AdminEmptyRequest } var file_proto_admin_proto_depIdxs = []int32{ 0, // 0: admin.Admin.AdminEdit:input_type -> admin.AdminEditRequest @@ -590,15 +629,17 @@ var file_proto_admin_proto_depIdxs = []int32{ 5, // 4: admin.Admin.AdminInfo:input_type -> admin.AdminInfoRequest 6, // 5: admin.Admin.AdminItems:input_type -> admin.AdminItemsRequest 7, // 6: admin.Admin.AdminLogin:input_type -> admin.AdminLoginRequest - 2, // 7: admin.Admin.AdminEdit:output_type -> admin.Response - 2, // 8: admin.Admin.AdminStatus:output_type -> admin.Response - 2, // 9: admin.Admin.Password:output_type -> admin.Response - 2, // 10: admin.Admin.OwnPassword:output_type -> admin.Response - 2, // 11: admin.Admin.AdminInfo:output_type -> admin.Response - 2, // 12: admin.Admin.AdminItems:output_type -> admin.Response - 2, // 13: admin.Admin.AdminLogin:output_type -> admin.Response - 7, // [7:14] is the sub-list for method output_type - 0, // [0:7] is the sub-list for method input_type + 8, // 7: admin.Admin.AdminRefresh:input_type -> admin.AdminEmptyRequest + 2, // 8: admin.Admin.AdminEdit:output_type -> admin.Response + 2, // 9: admin.Admin.AdminStatus:output_type -> admin.Response + 2, // 10: admin.Admin.Password:output_type -> admin.Response + 2, // 11: admin.Admin.OwnPassword:output_type -> admin.Response + 2, // 12: admin.Admin.AdminInfo:output_type -> admin.Response + 2, // 13: admin.Admin.AdminItems:output_type -> admin.Response + 2, // 14: admin.Admin.AdminLogin:output_type -> admin.Response + 2, // 15: admin.Admin.AdminRefresh:output_type -> admin.Response + 8, // [8:16] is the sub-list for method output_type + 0, // [0:8] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name @@ -615,7 +656,7 @@ func file_proto_admin_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_admin_proto_rawDesc), len(file_proto_admin_proto_rawDesc)), NumEnums: 0, - NumMessages: 8, + NumMessages: 9, NumExtensions: 0, NumServices: 1, }, diff --git a/admin/admin/admin_grpc.pb.go b/admin/admin/admin_grpc.pb.go index 43d80cd..fbc85f8 100644 --- a/admin/admin/admin_grpc.pb.go +++ b/admin/admin/admin_grpc.pb.go @@ -19,13 +19,14 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - Admin_AdminEdit_FullMethodName = "/admin.Admin/AdminEdit" - Admin_AdminStatus_FullMethodName = "/admin.Admin/AdminStatus" - Admin_Password_FullMethodName = "/admin.Admin/Password" - Admin_OwnPassword_FullMethodName = "/admin.Admin/OwnPassword" - Admin_AdminInfo_FullMethodName = "/admin.Admin/AdminInfo" - Admin_AdminItems_FullMethodName = "/admin.Admin/AdminItems" - Admin_AdminLogin_FullMethodName = "/admin.Admin/AdminLogin" + Admin_AdminEdit_FullMethodName = "/admin.Admin/AdminEdit" + Admin_AdminStatus_FullMethodName = "/admin.Admin/AdminStatus" + Admin_Password_FullMethodName = "/admin.Admin/Password" + Admin_OwnPassword_FullMethodName = "/admin.Admin/OwnPassword" + Admin_AdminInfo_FullMethodName = "/admin.Admin/AdminInfo" + Admin_AdminItems_FullMethodName = "/admin.Admin/AdminItems" + Admin_AdminLogin_FullMethodName = "/admin.Admin/AdminLogin" + Admin_AdminRefresh_FullMethodName = "/admin.Admin/AdminRefresh" ) // AdminClient is the client API for Admin service. @@ -39,6 +40,7 @@ type AdminClient interface { AdminInfo(ctx context.Context, in *AdminInfoRequest, opts ...grpc.CallOption) (*Response, error) AdminItems(ctx context.Context, in *AdminItemsRequest, opts ...grpc.CallOption) (*Response, error) AdminLogin(ctx context.Context, in *AdminLoginRequest, opts ...grpc.CallOption) (*Response, error) + AdminRefresh(ctx context.Context, in *AdminEmptyRequest, opts ...grpc.CallOption) (*Response, error) } type adminClient struct { @@ -119,6 +121,16 @@ func (c *adminClient) AdminLogin(ctx context.Context, in *AdminLoginRequest, opt return out, nil } +func (c *adminClient) AdminRefresh(ctx context.Context, in *AdminEmptyRequest, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, Admin_AdminRefresh_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // AdminServer is the server API for Admin service. // All implementations must embed UnimplementedAdminServer // for forward compatibility. @@ -130,6 +142,7 @@ type AdminServer interface { AdminInfo(context.Context, *AdminInfoRequest) (*Response, error) AdminItems(context.Context, *AdminItemsRequest) (*Response, error) AdminLogin(context.Context, *AdminLoginRequest) (*Response, error) + AdminRefresh(context.Context, *AdminEmptyRequest) (*Response, error) mustEmbedUnimplementedAdminServer() } @@ -161,6 +174,9 @@ func (UnimplementedAdminServer) AdminItems(context.Context, *AdminItemsRequest) func (UnimplementedAdminServer) AdminLogin(context.Context, *AdminLoginRequest) (*Response, error) { return nil, status.Error(codes.Unimplemented, "method AdminLogin not implemented") } +func (UnimplementedAdminServer) AdminRefresh(context.Context, *AdminEmptyRequest) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method AdminRefresh not implemented") +} func (UnimplementedAdminServer) mustEmbedUnimplementedAdminServer() {} func (UnimplementedAdminServer) testEmbeddedByValue() {} @@ -308,6 +324,24 @@ func _Admin_AdminLogin_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } +func _Admin_AdminRefresh_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AdminEmptyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminServer).AdminRefresh(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Admin_AdminRefresh_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminServer).AdminRefresh(ctx, req.(*AdminEmptyRequest)) + } + return interceptor(ctx, in, info, handler) +} + // Admin_ServiceDesc is the grpc.ServiceDesc for Admin service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -343,6 +377,10 @@ var Admin_ServiceDesc = grpc.ServiceDesc{ MethodName: "AdminLogin", Handler: _Admin_AdminLogin_Handler, }, + { + MethodName: "AdminRefresh", + Handler: _Admin_AdminRefresh_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "proto/admin.proto", diff --git a/admin/adminclient/admin.go b/admin/adminclient/admin.go index a9dc69b..c55693a 100644 --- a/admin/adminclient/admin.go +++ b/admin/adminclient/admin.go @@ -15,6 +15,7 @@ import ( type ( AdminEditRequest = admin.AdminEditRequest + AdminEmptyRequest = admin.AdminEmptyRequest AdminInfoRequest = admin.AdminInfoRequest AdminItemsRequest = admin.AdminItemsRequest AdminLoginRequest = admin.AdminLoginRequest @@ -24,7 +25,6 @@ type ( StatusRequest = admin.StatusRequest Admin interface { - AdminAdd(ctx context.Context, in *AdminEditRequest, opts ...grpc.CallOption) (*Response, error) AdminEdit(ctx context.Context, in *AdminEditRequest, opts ...grpc.CallOption) (*Response, error) AdminStatus(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*Response, error) Password(ctx context.Context, in *PasswordRequest, opts ...grpc.CallOption) (*Response, error) @@ -32,6 +32,7 @@ type ( AdminInfo(ctx context.Context, in *AdminInfoRequest, opts ...grpc.CallOption) (*Response, error) AdminItems(ctx context.Context, in *AdminItemsRequest, opts ...grpc.CallOption) (*Response, error) AdminLogin(ctx context.Context, in *AdminLoginRequest, opts ...grpc.CallOption) (*Response, error) + AdminRefresh(ctx context.Context, in *AdminEmptyRequest, opts ...grpc.CallOption) (*Response, error) } defaultAdmin struct { @@ -45,11 +46,6 @@ func NewAdmin(cli zrpc.Client) Admin { } } -func (m *defaultAdmin) AdminAdd(ctx context.Context, in *AdminEditRequest, opts ...grpc.CallOption) (*Response, error) { - client := admin.NewAdminClient(m.cli.Conn()) - return client.AdminAdd(ctx, in, opts...) -} - func (m *defaultAdmin) AdminEdit(ctx context.Context, in *AdminEditRequest, opts ...grpc.CallOption) (*Response, error) { client := admin.NewAdminClient(m.cli.Conn()) return client.AdminEdit(ctx, in, opts...) @@ -84,3 +80,8 @@ func (m *defaultAdmin) AdminLogin(ctx context.Context, in *AdminLoginRequest, op client := admin.NewAdminClient(m.cli.Conn()) return client.AdminLogin(ctx, in, opts...) } + +func (m *defaultAdmin) AdminRefresh(ctx context.Context, in *AdminEmptyRequest, opts ...grpc.CallOption) (*Response, error) { + client := admin.NewAdminClient(m.cli.Conn()) + return client.AdminRefresh(ctx, in, opts...) +} diff --git a/admin/internal/dao/login.go b/admin/internal/dao/login.go index b7689b5..6338074 100644 --- a/admin/internal/dao/login.go +++ b/admin/internal/dao/login.go @@ -16,7 +16,8 @@ type JwtInfo struct { } type Token struct { - Token string `json:"token"` + Token string `json:"token"` + Refresh string `json:"refresh"` } type JwtInfoServices struct { diff --git a/admin/internal/logic/adminloginlogic.go b/admin/internal/logic/adminloginlogic.go index e51a600..f3262ab 100644 --- a/admin/internal/logic/adminloginlogic.go +++ b/admin/internal/logic/adminloginlogic.go @@ -75,31 +75,48 @@ func (l *AdminLoginLogic) AdminLogin(in *admin.AdminLoginRequest) (*admin.Respon retData := dao.Token{ Token: utils.MD5Encrypt(data.Phone + utils.Now().String()), } + retData.Refresh = utils.MD5Encrypt(data.Phone + retData.Token) - l.setLogin(retData.Token, data) + l.setLogin(retData.Token, retData.Refresh, data) return l.ok(retData), nil } -func (l *AdminLoginLogic) setLogin(token string, data dao.JwtInfo) { +func (l *AdminLoginLogic) setLogin(token, refresh string, data dao.JwtInfo) { + //获取登录过期时间 expireMin := utils.GetConfigInt("base.login_out_time") - var expire time.Duration - // 默认使用配置时长 - expire = time.Duration(expireMin) * time.Minute - // 如果用户自定义了过期时间则覆盖 - if data.Time > utils.NumberZero { - expire = time.Duration(data.Time) * time.Minute - } - + expire := time.Duration(expireMin) * time.Minute + //获取刷新登录过期时间 + refreshMin := utils.GetConfigInt("base.login_refresh_out_time") + refreshExpire := time.Duration(refreshMin) * time.Minute + //登录信息写入redis redisKey := utils.GetLoginKey(utils.LoginTypeAdmin, token) - l.Logger.Error(redisKey) userStr, _ := jsoniter.Marshal(data) ctx := context.Background() redis.Client.Set(ctx, redisKey, userStr, expire).Result() - redisKeysKey := utils.GetLoginKeysKey(utils.LoginTypeAdmin) - oldAuth, oldErr := redis.Client.HGet(ctx, redisKeysKey, strconv.Itoa(int(data.Id))).Result() + + //获取原来的token与refresh + redisKeysKey := utils.GetLoginKeysKey(utils.LoginTypeAdmin, strconv.FormatInt(data.Id, 10)) + var LoginInfo utils.LoginRedis + oldAuth, oldErr := redis.Client.Get(ctx, redisKeysKey).Result() + //如果获取到了数据情况之前的 if oldErr == nil { - redis.Client.Del(ctx, utils.GetLoginKey(utils.LoginTypeAdmin, oldAuth)).Result() + _ = jsoniter.Unmarshal([]byte(oldAuth), &LoginInfo) + if len(LoginInfo.Token) > utils.NumberOne { + redis.Client.Del(ctx, utils.GetLoginKey(utils.LoginTypeAdmin, LoginInfo.Token)).Result() + } + if len(LoginInfo.Refresh) > utils.NumberOne { + redis.Client.Del(ctx, utils.GetLoginRefreshKey(utils.LoginTypeAdmin, LoginInfo.Refresh)).Result() + } } - redis.Client.HSet(ctx, redisKeysKey, strconv.Itoa(int(data.Id)), token).Result() + //更新新的数据 + LoginInfo.Token = token + LoginInfo.Refresh = refresh + LoginInfo.Info = userStr + newStr, _ := jsoniter.Marshal(LoginInfo) + redis.Client.Set(ctx, redisKeysKey, newStr, refreshExpire).Result() + //登录刷新信息写入redis + refreshKey := utils.GetLoginRefreshKey(utils.LoginTypeAdmin, refresh) + redis.Client.Set(ctx, refreshKey, strconv.FormatInt(data.Id, 10), refreshExpire).Result() + } diff --git a/admin/internal/logic/adminrefreshlogic.go b/admin/internal/logic/adminrefreshlogic.go new file mode 100644 index 0000000..0dec869 --- /dev/null +++ b/admin/internal/logic/adminrefreshlogic.go @@ -0,0 +1,86 @@ +package logic + +import ( + "admin/internal/dao" + "context" + "time" + + "admin/admin" + "admin/internal/svc" + + jsoniter "github.com/json-iterator/go" + "github.com/zeromicro/go-zero/core/logx" + "pkg.local/redis" + "pkg.local/utils" +) + +type AdminRefreshLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger + BaseLogic +} + +func NewAdminRefreshLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminRefreshLogic { + return &AdminRefreshLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *AdminRefreshLogic) AdminRefresh(in *admin.AdminEmptyRequest) (*admin.Response, error) { + adminInfo := utils.GetUserFromCtx(l.ctx) + l.Logger.Error(adminInfo) + if len(adminInfo.Refresh) < utils.NumberOne { + return l.fail(utils.ErrorNoLoginInfo), nil + } + + //获取登录过期时间 + expireMin := utils.GetConfigInt("base.login_out_time") + expire := time.Duration(expireMin) * time.Minute + //获取刷新登录过期时间 + refreshMin := utils.GetConfigInt("base.login_refresh_out_time") + refreshExpire := time.Duration(refreshMin) * time.Minute + //登录信息写入redis + refreshKey := utils.GetLoginRefreshKey(utils.LoginTypeAdmin, adminInfo.Refresh) + ctx := context.Background() + id, err := redis.Client.Get(ctx, refreshKey).Result() + if err != nil { + return l.fail(utils.ErrorNoLoginInfo), nil + } + + //获取原来的token与refresh + redisKeysKey := utils.GetLoginKeysKey(utils.LoginTypeAdmin, id) + var LoginInfo utils.LoginRedis + oldAuth, oldErr := redis.Client.Get(ctx, redisKeysKey).Result() + if oldErr != nil { + return l.fail(utils.ErrorNoLoginInfo), nil + } + _ = jsoniter.Unmarshal([]byte(oldAuth), &LoginInfo) + if len(LoginInfo.Token) > utils.NumberOne { + redis.Client.Del(ctx, utils.GetLoginKey(utils.LoginTypeAdmin, LoginInfo.Token)).Result() + } + if len(LoginInfo.Refresh) > utils.NumberOne { + redis.Client.Del(ctx, utils.GetLoginRefreshKey(utils.LoginTypeAdmin, LoginInfo.Refresh)).Result() + } + + retData := dao.Token{ + Token: utils.MD5Encrypt(id + utils.Now().String()), + } + retData.Refresh = utils.MD5Encrypt(id + retData.Token) + + redisKey := utils.GetLoginKey(utils.LoginTypeAdmin, retData.Token) + redis.Client.Set(ctx, redisKey, LoginInfo.Info, expire).Result() + + //更新新的数据 + LoginInfo.Token = retData.Token + LoginInfo.Refresh = retData.Refresh + newStr, _ := jsoniter.Marshal(LoginInfo) + redis.Client.Set(ctx, redisKeysKey, newStr, refreshExpire).Result() + //登录刷新信息写入redis + newRefreshKey := utils.GetLoginRefreshKey(utils.LoginTypeAdmin, retData.Refresh) + redis.Client.Set(ctx, newRefreshKey, id, refreshExpire).Result() + + return l.ok(retData), nil +} diff --git a/admin/internal/server/adminserver.go b/admin/internal/server/adminserver.go index 71edd44..f881fd9 100644 --- a/admin/internal/server/adminserver.go +++ b/admin/internal/server/adminserver.go @@ -57,3 +57,8 @@ func (s *AdminServer) AdminLogin(ctx context.Context, in *admin.AdminLoginReques l := logic.NewAdminLoginLogic(ctx, s.svcCtx) return l.AdminLogin(in) } + +func (s *AdminServer) AdminRefresh(ctx context.Context, in *admin.AdminEmptyRequest) (*admin.Response, error) { + l := logic.NewAdminRefreshLogic(ctx, s.svcCtx) + return l.AdminRefresh(in) +} diff --git a/admin/proto/admin.proto b/admin/proto/admin.proto index 69cc4f5..9c69f9f 100644 --- a/admin/proto/admin.proto +++ b/admin/proto/admin.proto @@ -55,6 +55,9 @@ message AdminLoginRequest { string password = 2; } +message AdminEmptyRequest { +} + service Admin { rpc AdminEdit(AdminEditRequest) returns(Response){ option (google.api.http) = { @@ -98,4 +101,10 @@ service Admin { body: "*" }; }; + rpc AdminRefresh(AdminEmptyRequest) returns(Response){ + option (google.api.http) = { + post: "/admin/v3/refresh" + body: "*" + }; + }; } \ No newline at end of file diff --git a/bff/etc/admin.pb b/bff/etc/admin.pb index 33b431b4a8be33ca1b375e74a54e791bec4fa5d0..ba1d8387fe8249700abf6d9ed17b229406f1e06a 100644 GIT binary patch delta 133 zcmaD~bhmiJV`Ii2o1YkeXOd77<`Q&F$<54j%`GUY3`#95O)V}ly3V@!o>?7}vQRh| z4_G!RHLWPMI73K6FA=0z520o9Sqn)6nWoE6CNqgC3F?ET^~;R)iy%6z7`2=@quBKz N5=m?YMfoN9#sGNAFgpMM delta 43 zcmcax{Jv 0 then - red:select(redis_db) - end - - -- ========== 获取用户信息 ========== - local res, err = red:get(redis_key) - red:set_keepalive(10000, 100) - - if err then - core.log.error("Redis get error: ", err) - return core.response.exit(500, { - code = 10003, - message = "系统错误,请稍后重试", - data = nil - }) - end - - if not res or res == ngx.null then - core.log.warn("User not found in redis, key: ", redis_key) - return core.response.exit(401, { - code = 10003, - message = "未登录或登录已过期", - data = nil - }) - end - - -- ========== 解析用户信息 ========== - local json, decode_err = core.json.decode(res) - if not json then - core.log.error("JSON decode error: ", decode_err, " data: ", res) - return core.response.exit(500, { - code = 10003, - message = "数据解析错误", - data = nil - }) - end - - -- ========== Admin路径权限校验 ========== - if service_code == "admin1" then - if not req_auth or req_auth == "" then - core.log.warn("Missing Authorization-Auth header for admin") - return core.response.exit(403, { - code = 10008, - message = "没有权限访问该资源", - data = nil - }) + if redis_password ~= "" then + local auth_ok, auth_err = red:auth(redis_password) + if not auth_ok then + red:set_keepalive(10000, 100) + return core.response.exit(500, {code = 10003, message = "系统错误,请稍后重试"}) + end + end + if redis_db > 0 then + red:select(redis_db) end - local roles = json.roles or {} - local expect_path = roles[req_auth] - - if not expect_path or expect_path == "" then - core.log.error("Permission not found for auth: ", req_auth, - " user_id: ", json.id, " roles: ", core.json.encode(roles)) - return core.response.exit(403, { - code = 10008, - message = "没有权限访问该资源", - data = nil - }) + local res, err = red:get(redis_key) + red:set_keepalive(10000, 100) + if err or res == ngx.null then + return core.response.exit(401, {code = 10003, message = "未登录或登录已过期"}) + end + local json, decode_err = core.json.decode(res) + if not json then + return core.response.exit(500, {code = 10003, message = "数据解析错误"}) end - local full_expect_uri = "/" .. expect_path - - if request_uri ~= full_expect_uri then - local is_prefix_match = false + if service_code == "admin1" then + if not req_auth or req_auth == "" then + return core.response.exit(403, {code = 10008, message = "没有权限访问该资源"}) + end + local roles = json.roles or {} + local expect_path = roles[req_auth] + if not expect_path then + return core.response.exit(403, {code = 10008, message = "没有权限访问该资源"}) + end + local full_expect_uri = "/" .. expect_path + local match = false if expect_path:sub(-1) == "*" then - local base_path = expect_path:sub(1, -2) - if request_uri:find(base_path, 1, true) == 1 then - is_prefix_match = true + local base = expect_path:sub(1, -2) + if request_uri:find(base, 1, true) == 1 then + match = true end end - - if not is_prefix_match then - core.log.error("URI mismatch - request: ", request_uri, - " expected: ", full_expect_uri, - " auth: ", req_auth, - " user_id: ", json.id) - return core.response.exit(403, { - code = 10008, - message = "没有权限访问该资源", - data = nil - }) + if request_uri ~= full_expect_uri and not match then + return core.response.exit(403, {code = 10008, message = "没有权限访问该资源"}) end end + + if json.id then + ngx.req.set_header("X-User-Id", tostring(json.id)) + end + if json.name then + ngx.req.set_header("X-User-Name", json.name) + end + if json.username then + ngx.req.set_header("X-Username", json.username) + end end - -- ========== 向下游透传用户信息 ========== - if json.id then - ngx.req.set_header("X-User-Id", tostring(json.id)) - end - - if json.name then - ngx.req.set_header("X-User-Name", json.name) - end - - if json.username then - ngx.req.set_header("X-Username", json.username) - end - ngx.req.set_header("X-Refresh", refresh ) - - ngx.req.set_header("X-Service-Code", service_code) + ngx.req.set_header("X-Refresh", refresh or "") + ngx.req.set_header("X-Service-Code", service_code or "") + core.log.info("FINAL_SET_HEADER: X-Refresh=["..(refresh or "").."]") return end diff --git a/pkg/utils/config.go b/pkg/utils/config.go index 52fac1d..4787273 100644 --- a/pkg/utils/config.go +++ b/pkg/utils/config.go @@ -34,7 +34,8 @@ func GetConfigString(key string) string { } func GetConfigInt(key string) int { data := make(map[string]int) - data["base.login_out_time"] = 60 * 24 * 30 //分 + data["base.login_out_time"] = 60 * 24 * 30 //分 + data["base.login_refresh_out_time"] = 60 * 24 * 30 * 2 //分 return data[key] } func GetConfigInt64(key string) int64 { return runViper.GetInt64(key) } diff --git a/pkg/utils/loginInfo.go b/pkg/utils/loginInfo.go index b99153f..2e9de53 100644 --- a/pkg/utils/loginInfo.go +++ b/pkg/utils/loginInfo.go @@ -16,17 +16,19 @@ type UserInfo struct { Valid bool } -// GetUserFromCtx 从rpc metadata获取用户 func GetUserFromCtx(ctx context.Context) UserInfo { md, ok := metadata.FromIncomingContext(ctx) if !ok { return UserInfo{Valid: false} } - uidList := md.Get("x-user-id") nameList := md.Get("x-user-name") refreshList := md.Get("x-refresh") + if len(refreshList) == 0 { + refreshList = md.Get("X-Refresh") + } + rawUID := "" encodeName := "" refresh := "" @@ -41,7 +43,7 @@ func GetUserFromCtx(ctx context.Context) UserInfo { } if rawUID == "" { - return UserInfo{Valid: false} + return UserInfo{Valid: false, Refresh: refresh} } uid, err := strconv.ParseInt(rawUID, 10, 64) @@ -54,7 +56,6 @@ func GetUserFromCtx(ctx context.Context) UserInfo { } } - // 解码中文 userName, _ := url.QueryUnescape(encodeName) return UserInfo{ diff --git a/pkg/utils/status.go b/pkg/utils/status.go index 4b735f9..195dd2a 100644 --- a/pkg/utils/status.go +++ b/pkg/utils/status.go @@ -7,6 +7,12 @@ type Status struct { Msg string `json:"message"` } +type LoginRedis struct { + Info interface{} `json:"info"` + Token string `json:"token"` + Refresh string `json:"refresh"` +} + const ( NumberMinusOne = -1 NumberZero = 0 @@ -45,10 +51,11 @@ const ( const ( // LoginUser 所有的登录 加上服务名:id // %s 为,admin,user ,... - Login = "login:service:%s:" - LoginKey = "login:service:%s:keys" - LoginTypeAdmin = "admin" - LoginTypeUser = "user" + Login = "login:service:%s:" + LoginKey = "login:service:%s:token:" + LoginRefreshKey = "login:service:%s:refresh:" + LoginTypeAdmin = "admin" + LoginTypeUser = "user" CodeKey = "code:" ) @@ -107,6 +114,10 @@ func GetLoginKey(Type, key string) string { return fmt.Sprintf(Login, Type) + key } -func GetLoginKeysKey(Type string) string { - return fmt.Sprintf(LoginKey, Type) +func GetLoginKeysKey(Type string, key string) string { + return fmt.Sprintf(LoginKey, Type) + key +} + +func GetLoginRefreshKey(Type string, key string) string { + return fmt.Sprintf(LoginRefreshKey, Type) + key }