序
如果在程序中,要带口令访问mongoDB, 需要设置mongoDB的授权参数,建立用户等操作。
看到人家已经做好了这个实验, 自己也验证了一下。
发现了一个小坑,/etc/mongod.conf中是新语法,是有层级的,下一个层级的内容开始位置不要用\t,而是2个空格才生效。刚装完的mongoDB3.4的mongod.conf中有些例子,才知道要用2个空格代替\t.
虽然旧语法也能用在mongod.conf中,也好使。但是为了避免未知坑,还是用新语法。
要跟着官方文裆,测试用例,示例走,才能少入坑。
实验
设置mongodb3.4的授权
对应的mongo-cxx-driver版本为3.1.1
> use admin
switched to db admin
> db.createUser({ user: "admin", pwd: "adminpassword", roles: [{ role: "userAdminAnyDatabase", db: "admin" }] })
Successfully added user: {
"user" : "admin",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}
> db.auth("admin", "adminpassword")
1
> exit
bye
sudo vi /etc/mongod.conf
add code below after #security:
// authorization前面是2个空格, 不能是\t
#security:
security:
authorization: enabled
# not below, don't table key, need 2 space
#security:
# authorization: enabled
sudo service mongod restart
now mongod error, not start
if mongod was run, info below
sudo service mongod status
[ ok ] Checking status of database: mongod running.
sudo service mongod status
[FAIL] Checking status of database: mongod apparently not running failed!
///////////////////////////////////////
back to mongo
> use admin
switched to db admin
> db.auth("admin", "adminpassword")
1
> use test
switched to db test
> db.createUser({ user: "test_usr", pwd: "test_pwd", roles: [{ role: "dbOwner", db: "test" }] })
Successfully added user: {
"user" : "test_usr",
"roles" : [
{
"role" : "dbOwner",
"db" : "test"
}
]
}
> db.auth("test_usr", "test_pwd")
1
> show collections
fs.chunks
fs.files
// the author uri is below
mongodb://youruser:yourpassword@localhost/yourdatabase
mongodb://test_usr:test_pwd@localhost/test
写测试程序进行带口令登录验证
只有增删改查时,才会用到用户登录后的权限。
如果不带口令登录,不是一上来就报错,而是要增删改查时,才抛未登录异常。
bool class_mongo_opt::test()
{
bool b_rc = false;
std::string errmsg;
int i_bp_index = 0;
printf(">> class_mongo_opt::test() v1.0.0.1\n");
try {
// https://docs.mongodb.com/master/reference/connection-string/
// mongodb://192.168.2.60:27017
// mongodb://test_usr:test_pwd@localhost/test
// mongocxx::exception& ex = not authorized on test to execute command { aggregate: "restaurants", pipeline: [ { $group: { _id: "$borough", count: { $sum: 1 } } } ], cursor: {} }: generic server error
printf("bp = %d\n", i_bp_index++);
mongocxx::instance inst{}; // This should be done only once.
printf("bp = %d\n", i_bp_index++);
// 无认证的写法
mongocxx::client conn{mongocxx::uri{}};
// 有认证的写法
/*
mongocxx::uri uri("mongodb://test_usr:test_pwd@localhost:27017/test");
mongocxx::client conn(uri);
*/
printf("bp = %d\n", i_bp_index++);
auto db = conn["test"];
// Group documents by field and calculate count.
{
// @begin: cpp-group-documents-by-a-field-and-calculate-count
printf("1 bp = %d\n", i_bp_index++);
mongocxx::pipeline stages;
printf("bp = %d\n", i_bp_index++);
bsoncxx::builder::stream::document group_stage;
printf("bp = %d\n", i_bp_index++);
group_stage << "_id"
<< "$borough"
<< "count" << open_document << "$sum" << 1 << close_document;
printf("bp = %d\n", i_bp_index++);
stages.group(group_stage.view());
printf("bp = %d\n", i_bp_index++);
auto cursor = db["restaurants"].aggregate(stages);
printf("8 bp = %d\n", i_bp_index++);
// mongocxx::exception& ex = not authorized on test to execute command { aggregate: "restaurants", pipeline: [ { $group: { _id: "$borough", count: { $sum: 1 } } } ], cursor: {} }: generic server error
// cursor 遍历时,需要登录数据库后才有权限
for (auto&& doc : cursor) {
printf("10 bp = %d\n", i_bp_index++);
std::cout << bsoncxx::to_json(doc) << std::endl;
}
// @end: cpp-group-documents-by-a-field-and-calculate-count
printf("9 bp = %d\n", i_bp_index++);
}
// Filter and group documents.
{
// @begin: cpp-filter-and-group-documents
printf("3 bp = %d\n", i_bp_index++);
mongocxx::pipeline stages;
printf("bp = %d\n", i_bp_index++);
bsoncxx::builder::stream::document match_stage, group_stage;
printf("bp = %d\n", i_bp_index++);
match_stage << "borough"
<< "Queens"
<< "cuisine"
<< "Brazilian";
printf("bp = %d\n", i_bp_index++);
group_stage << "_id"
<< "$address.zipcode"
<< "count" << open_document << "$sum" << 1 << close_document;
printf("bp = %d\n", i_bp_index++);
stages.match(match_stage.view()).group(group_stage.view());
printf("bp = %d\n", i_bp_index++);
auto cursor = db["restaurants"].aggregate(stages);
printf("bp = %d\n", i_bp_index++);
for (auto&& doc : cursor) {
printf("bp = %d\n", i_bp_index++);
std::cout << bsoncxx::to_json(doc) << std::endl;
}
// @end: cpp-filter-and-group-documents
printf("4 bp = %d\n", i_bp_index++);
}
b_rc = true;
}
/*
catch(mongocxx::exception& ex) {
printf("mongocxx::exception& ex = %s\n", ex.what());
b_rc = false;
}
*/
catch(std::exception& ex) {
errmsg = ex.what();
printf("exception : %s\n", errmsg.c_str());
b_rc = false;
}
catch(...) {
printf("catch...\n");
b_rc = false;
}
return b_rc;
}