MongoDB Authentication

最近因为博客抽风了一下下,所以重置了一下 VPS,顺便从有点蠢蠢的 Ubuntu 换成了纯洁的也蠢蠢的 Debian。重置之前忘记了一件很重要的事:Kiyoshi IoT 的数据是来自这一台服务器的 MongoDB。虽然数据不是那么重要,但是这个小页面还是要的!毕竟会让我觉得自己还是能做点小项目的(虽然屁用都没有吧!)。

在以前这个 MongoDB Server 都是没开 Authentication 的,只要连接就可以上 —— 因为 Kiyoshi 心大而且没有重要数据!但是今天有点想折腾一下,顺便读一点点 MongoDB 的文档啦!

问题

一个毫无保护的 MongoDB 是不得行的!所以要开启 MongoDB 的 Access Control!

解决方案

在 MongoDB 官方文档中的 Enable Access Control 部分中有提到:

The following procedure first adds a user administrator to a MongoDB instance running without access control and then enables access control.

所以第一步是创建用户啦。

实现过程

该过程是完全照着官方文档走的!原味的才是最棒的嗷!

启动 MongoDB

创建用户之前,要先启动 MongoDB Server!

1
2
3
4
5
# terminal 中启动
mongod --port 27017 --dbpath /path/to/db

# 以 service 启动
service mongod start

因为我不喜欢开太多框框,所以这里是直接 service 启动!

连接到 MongoDB

接着在本地以 mongo shell 的形式连接到 MongoDB:

1
2
# 若端口为默认的 27017 则可以不用指定 --port 参数
mongo --port 27017

创建用户管理员

在 mongo shell 中,向 admin 创建一个身份为 userAdminAnyDatabase 的用户。一个用户可以有多重身份,所以在创建的时候也可以将其他的身份一并赋予新用户。根据官方文档为了以后的方便,可以创建一个身份为 userAdminAnyDatabasereadWriteAnyDatabase 的用户。

在 MongoDB 中不同的身份拥有不同的权限。

注:MongoDB 自带身份说明:MongoDB Built-In Roles

1
2
3
4
5
6
7
8
use admin // 切换到 admin database
db.createUser(
{
user: "myUserAdmin", // 用户名
pwd: passwordPrompt(), // 通过标准输入录入密码;当然也可以直接在这里以明文的方式进行输入;这是 MongoDB 4.2 的新特性,低于 4.2 就别用啦
roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ] // 身份信息
}
)

在官方文档中有提到:

The database where you create the user (in this example, admin) is the user’s authentication database. Although the user would authenticate to this database, the user can have roles in other databases; i.e. the user’s authentication database does not limit the user’s privileges.

也就是说是否在 admin 中创建这个用户并不会影响该用户的权限;它也可以访问其他的数据库。但是 Kiyoshi 感觉在 admin 中创建所有的管理员账户应该是惯例。

重启 MongoDB 并开启 Access Control

  1. 为了让用户生效,需要重启 MongoDB 啦。

    1
    db.adminCommand( { shutdown: 1 } )

    这样 MongoDB 就会暂时停止工作。

  2. 退出 mongo shell

    1
    exit
  3. 重新启动开启了 Access Control 的 MongoDB

    若要从终端直接开启 MongoDB:

    1
    2
    # --auth 参数开启了 Access Control
    mongod --auth --port 27017 --dbpath /path/to/db

    如果是通过 service 启动 MongoDB,或是想要将 Access Control 作为启动 MongoDB 的默认选项,需要修改 MongoDB 的配置文件。默认路径通常为 mongod.conf

    在配置文件中找到 security 项,取消注释,添加配置:

    1
    2
    3
    # MongoDB config convention 应该为两个空格
    security:
    authorization: enable

    注:MongoDB 配置文件说明:Configuration File Options

  4. 以管理员身份连接到 MongoDB

    现在 MongoDB 已经不能直接访问了,如果直接访问某一个数据库会被拒绝访问。可以尝试使用管理员账户登录啦:

    1
    mongo --port 27017  --authenticationDatabase "admin" -u "myUserAdmin" -p

    在 mongo shell 的提示下输入密码就可以登录啦!

    当然也有剑走偏锋的方式进行登录:在连接上 MongoDB 后再进行认证。

    首先连接到数据库:

    1
    mongo --port 27017

    接着切换到 admin 并进行用户认证:

    1
    2
    use admin
    db.auth("myUserAdmin", passwordPrompt()) // 和创建用户一样,也可以在这里直接输入明文密码

根据需求创建需要的用户

只要使用了用户管理员的账号认证后,就可以使用 db.createUser() 这个方法来继续创建额外的用户啦。用户身份既可以是内置身份,也可以使用自己定义的身份:User-Defined Roles

直接照搬了官方的例子

这里的代码在 test 库中创建了一个叫 myTester,拥有 test 库读写身份 readWritereporting 库只读身份 read 的用户。

1
2
3
4
5
6
7
8
9
use test
db.createUser(
{
user: "myTester",
pwd: passwordPrompt(),
roles: [ { role: "readWrite", db: "test" },
{ role: "read", db: "reporting" } ]
}
)

接着可以从 mongo shell 中断开连接并尝试用新的用户登录啦。

使用新用户登录

按照之前登录的方式,以新用户的账户通过 mongo shell 登录:

1
mongo --port 27017 -u "myTester" --authenticationDatabase "test" -p

1
mongo --port 27017

接着切换到 test 并进行用户认证:

1
2
use test
db.auth("myTester", passwordPrompt())

在库中插入数据

登入库里之后,以 myTester 的身份在 test 库的 foo 集合中插入数据:

1
2
use test
db.foo.insert( { x: 1, y: 1 } )

如果你有可视化工具或是直接进行查询的话,就已经可以看到这一条数据的存在啦!

1
2
// 查询集合中第一条数据
db.foo.find()

至此,MongoDB 简单的用户认证就做好啦!

总结

在以前我的 MongoDB 一直是开放的状况,谁都能访问;随便扫扫我服务器的端口就知道我开了 MongoDB 虽然没人在意,总觉得怪怪的!现在有了一点点点点的保护,感觉有点舒服!就当学习啦。

End - of - File

文章作者: Takahashi Kiyoshi
文章链接: https://blog.k1yoshi.com/article/mongodb-auth/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Kiyoshi's Blog