31
31
32
32
DEFINE_int32 (port, 6379 , " TCP Port of this server" );
33
33
34
+ class AuthSession : public brpc ::Destroyable {
35
+ public:
36
+ explicit AuthSession (const std::string& user_name, const std::string& password)
37
+ : _user_name(user_name), _password(password) {}
38
+
39
+ void Destroy () override {
40
+ delete this ;
41
+ }
42
+
43
+ const std::string _user_name;
44
+ const std::string _password;
45
+ };
46
+
34
47
class RedisServiceImpl : public brpc ::RedisService {
35
48
public:
36
- bool Set (const std::string& key, const std::string& value) {
49
+ RedisServiceImpl () {
50
+ _user_password[" db1" ] = " 123456" ;
51
+ _user_password[" db2" ] = " 123456" ;
52
+ _db_map[" db1" ].resize (kHashSlotNum );
53
+ _db_map[" db2" ].resize (kHashSlotNum );
54
+ }
55
+
56
+ bool Set (const std::string& db_name, const std::string& key, const std::string& value) {
37
57
int slot = butil::crc32c::Value (key.c_str (), key.size ()) % kHashSlotNum ;
38
58
_mutex[slot].lock ();
39
- _map[slot][key] = value;
59
+ auto & kv = _db_map[db_name];
60
+ kv[slot][key] = value;
40
61
_mutex[slot].unlock ();
41
62
return true ;
42
63
}
43
64
44
- bool Get (const std::string& key, std::string* value) {
65
+ bool Auth (const std::string& db_name, const std::string& password) {
66
+ if (_user_password.find (db_name) == _user_password.end ()) {
67
+ return false ;
68
+ } else {
69
+ if (_user_password[db_name] != password) {
70
+ return false ;
71
+ }
72
+ }
73
+ return true ;
74
+ }
75
+
76
+ bool Get (const std::string& db_name, const std::string& key, std::string* value) {
45
77
int slot = butil::crc32c::Value (key.c_str (), key.size ()) % kHashSlotNum ;
46
78
_mutex[slot].lock ();
47
- auto it = _map[slot].find (key);
48
- if (it == _map[slot].end ()) {
79
+ auto & kv = _db_map[db_name];
80
+ auto it = kv[slot].find (key);
81
+ if (it == kv[slot].end ()) {
49
82
_mutex[slot].unlock ();
50
83
return false ;
51
84
}
@@ -56,7 +89,9 @@ class RedisServiceImpl : public brpc::RedisService {
56
89
57
90
private:
58
91
const static int kHashSlotNum = 32 ;
59
- std::unordered_map<std::string, std::string> _map[kHashSlotNum ];
92
+ typedef std::unordered_map<std::string, std::string> KVStore;
93
+ std::unordered_map<std::string, std::vector<KVStore>> _db_map;
94
+ std::unordered_map<std::string, std::string> _user_password;
60
95
butil::Mutex _mutex[kHashSlotNum ];
61
96
};
62
97
@@ -65,16 +100,27 @@ class GetCommandHandler : public brpc::RedisCommandHandler {
65
100
explicit GetCommandHandler (RedisServiceImpl* rsimpl)
66
101
: _rsimpl(rsimpl) {}
67
102
68
- brpc::RedisCommandHandlerResult Run (const std::vector<butil::StringPiece>& args,
103
+ brpc::RedisCommandHandlerResult Run (brpc::RedisConnContext* ctx,
104
+ const std::vector<butil::StringPiece>& args,
69
105
brpc::RedisReply* output,
70
106
bool /* flush_batched*/ ) override {
107
+
108
+ AuthSession* session = static_cast <AuthSession*>(ctx->get_session ());
109
+ if (session == nullptr ) {
110
+ output->FormatError (" No auth session" );
111
+ return brpc::REDIS_CMD_HANDLED;
112
+ }
113
+ if (session->_user_name .empty ()) {
114
+ output->FormatError (" No user name" );
115
+ return brpc::REDIS_CMD_HANDLED;
116
+ }
71
117
if (args.size () != 2ul ) {
72
118
output->FormatError (" Expect 1 arg for 'get', actually %lu" , args.size ()-1 );
73
119
return brpc::REDIS_CMD_HANDLED;
74
120
}
75
121
const std::string key (args[1 ].data (), args[1 ].size ());
76
122
std::string value;
77
- if (_rsimpl->Get (key, &value)) {
123
+ if (_rsimpl->Get (session-> _user_name , key, &value)) {
78
124
output->SetString (value);
79
125
} else {
80
126
output->SetNullString ();
@@ -91,32 +137,76 @@ class SetCommandHandler : public brpc::RedisCommandHandler {
91
137
explicit SetCommandHandler (RedisServiceImpl* rsimpl)
92
138
: _rsimpl(rsimpl) {}
93
139
94
- brpc::RedisCommandHandlerResult Run (const std::vector<butil::StringPiece>& args,
140
+ brpc::RedisCommandHandlerResult Run (brpc::RedisConnContext* ctx,
141
+ const std::vector<butil::StringPiece>& args,
95
142
brpc::RedisReply* output,
96
143
bool /* flush_batched*/ ) override {
144
+ AuthSession* session = static_cast <AuthSession*>(ctx->get_session ());
145
+ if (session == nullptr ) {
146
+ output->FormatError (" No auth session" );
147
+ return brpc::REDIS_CMD_HANDLED;
148
+ }
149
+ if (session->_user_name .empty ()) {
150
+ output->FormatError (" No user name" );
151
+ return brpc::REDIS_CMD_HANDLED;
152
+ }
97
153
if (args.size () != 3ul ) {
98
154
output->FormatError (" Expect 2 args for 'set', actually %lu" , args.size ()-1 );
99
155
return brpc::REDIS_CMD_HANDLED;
100
156
}
101
157
const std::string key (args[1 ].data (), args[1 ].size ());
102
158
const std::string value (args[2 ].data (), args[2 ].size ());
103
- _rsimpl->Set (key, value);
159
+ _rsimpl->Set (session-> _user_name , key, value);
104
160
output->SetStatus (" OK" );
105
161
return brpc::REDIS_CMD_HANDLED;
106
162
}
107
163
108
164
private:
109
- RedisServiceImpl* _rsimpl;
165
+ RedisServiceImpl* _rsimpl;
166
+ };
167
+
168
+
169
+
170
+ class AuthCommandHandler : public brpc ::RedisCommandHandler {
171
+ public:
172
+ explicit AuthCommandHandler (RedisServiceImpl* rsimpl)
173
+ : _rsimpl(rsimpl) {}
174
+ brpc::RedisCommandHandlerResult Run (brpc::RedisConnContext* ctx,
175
+ const std::vector<butil::StringPiece>& args,
176
+ brpc::RedisReply* output,
177
+ bool /* flush_batched*/ ) override {
178
+ if (args.size () != 3ul ) {
179
+ output->FormatError (" Expect 2 args for 'auth', actually %lu" , args.size ()-1 );
180
+ return brpc::REDIS_CMD_HANDLED;
181
+ }
182
+
183
+ const std::string db_name (args[1 ].data (), args[1 ].size ());
184
+ const std::string password (args[2 ].data (), args[2 ].size ());
185
+
186
+ if (_rsimpl->Auth (db_name, password)) {
187
+ output->SetStatus (" OK" );
188
+ auto auth_session = new AuthSession (db_name, password);
189
+ ctx->reset_session (auth_session);
190
+ } else {
191
+ output->FormatError (" Invalid password for database '%s'" , db_name.c_str ());
192
+ }
193
+ return brpc::REDIS_CMD_HANDLED;
194
+ }
195
+
196
+ private:
197
+ RedisServiceImpl* _rsimpl;
110
198
};
111
199
112
200
int main (int argc, char * argv[]) {
113
201
google::ParseCommandLineFlags (&argc, &argv, true );
114
202
RedisServiceImpl *rsimpl = new RedisServiceImpl;
115
203
auto get_handler =std::unique_ptr<GetCommandHandler>(new GetCommandHandler (rsimpl));
116
204
auto set_handler =std::unique_ptr<SetCommandHandler>( new SetCommandHandler (rsimpl));
205
+ auto auth_handler = std::unique_ptr<AuthCommandHandler>(new AuthCommandHandler (rsimpl));
117
206
rsimpl->AddCommandHandler (" get" , get_handler.get ());
118
207
rsimpl->AddCommandHandler (" set" , set_handler.get ());
119
-
208
+ rsimpl->AddCommandHandler (" auth" , auth_handler.get ());
209
+
120
210
brpc::Server server;
121
211
brpc::ServerOptions server_options;
122
212
server_options.redis_service = rsimpl;
0 commit comments