从零开始的Koa实战(4) MongoDB

我们使用 MongoDB 为应用提供可扩展的高性能数据存储解决方案。

MongoDB是一种面向文档的数据库管理系统,用C++等语言撰写而成,以此来解决应用程序开发社区中的大量现实问题。2007年10月,MongoDB由10gen团队所发展。2009年2月首度推出。 - 维基百科

本节实战将在 Windows 系统安装 MongoDB (Linux 下安装 MongoDB 可以参考 这里 ),将包含如下内容:

  • 安装 MongoDB
  • MongoDB 设置、启动、连接
  • MongoDB 用户创建、更新、删除

安装MongoDB

下载 MongoDB 安装文件,下载地址, 可以从其中选择需要的版本(本机为例:mongodb-win32-x86_64-2008plus-ssl-3.4.5-signed.msi)。下载完成后之后,双击执行安装,安装过程不再描述。

为了方便在命令行执行 mongodmongo 命令, 需要将安装路径添加到系统环境变量。
计算机-属性-高级系统设置-环境变量,找到path,双击编辑,在里面添加上面的安装目录(本机为例:C:\Program Files\MongoDB\Server\3.4\bin),添加完成后可以在命令行执行:

$ mongod

执行之后获得如下图结果,证明我们的环境变量添加成功:

MongoDB环境变量.png

MongoDB设置、启动、连接

我们的数据是以文件的方式存储在硬盘上面的,因此需要在系统磁盘新建数据库存放目录(以本机为例: C:\MongoDBC:\MongoDB\dbC:\MongoDB\log )。

方式一:命令行指定数据库位置

打开命令面板(快捷键 win+r 输入 cmd 回车),注意,需要以管理员身份在命令行执行:

$ mongod --bind_ip 127.0.0.1 --logpath "C:\MongoDB\log\mongod.log" --logappend --dbpath "C:\MongoDB\db" --port 3001 --serviceName "koa-blog" --serviceDisplayName "koa-blog" --install

上面的命令实际上是对 MongoDB 数据库进行了设置:

  • bind_ip:绑定IP地址,这里的127.0.0.1是指只有本机可以访问。
  • logpath:指定MongoDB的日志记录文件的位置。
  • logappend:指定日志的记录形式为追加形式。
  • dbpath:指定数据库的位置(注意,这不是安装MongoDB的位置,而是存放数据的位置)。
  • port:指定数据库运行在哪个端口,上面的示例选择3001端口。

后面的 --serviceName "koa-blog" --serviceDisplayName "koa-blog" --install 是将我们的这个命令安装成 Windows 的服务,可以在启动 Windows 系统的时候就启动这个服务,当然我们可以选择去掉这一段,那么以后需要启动服务器都要执行一次命令。

方式二:使用配置文件

为了方便并且有效可靠的记住服务器的配置,可以写一个配置文件,我们新建一个 C:\MongoDB\mongod.cfg 文件,内容为:

systemLog:
 destination: file
 path: "C:\\MongoDB\\log\\mongod.log"
 logAppend: true
net:
 bindIp: 127.0.0.1
 port: 3001
storage:
 dbPath: "C:\\MongoDB\\db"

接下来执行:

$ mongod --config "C:\MongoDB\mongod.cfg" --serviceName "koa-blog" --serviceDisplayName "koa-blog" --install

这样我们就对数据库进行了设置,并且安装到了 Windows 的 service,实际效果和方式一是一样的。

踩坑问题处理

如果发生如下问题

Error parsing YAML config file: YAML-cpp: error at line 2, column 13 : illegal map value

可以使用使用空格代替tab,在“:”之后也使用一个空格

YAML doesn't really satisfy with tabs, then, use space instead before destination and storage. Don't forget to add a space after every ":" even in the lines systemLog and storage Finally, use quotes to enclose your pathes and double backslashes in these pathes.

查看数据库配置是否成功

选择上面介绍的任一方式对数据库进行设置,执行成功之后,都可以看到 log 目录下面生成了一个 .log 后缀文件(本机为例:C:\MongoDB\log\mongod.log ),打开查看内容如下:

2019-11-04T15:56:50.104+0800 I CONTROL  [main] Trying to install Windows service 'koa-blog'
2019-11-04T15:56:50.492+0800 I CONTROL  [main] Service 'koa-blog' (koa-blog) installed with command line '"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe" --config C:\MongoDB\mongod.cfg --service'
2019-11-04T15:56:50.492+0800 I CONTROL  [main] Service can be started from the command line with 'net start koa-blog'

启动数据库

可以通过 net start koa-blog 启动服务器,我们来试试,以管理员身份在命令行执行:

$ net start koa-blog
MongoDB配置和启动.png

现如图的结果,表示数据库已经启动,我们看到 C:\MongoDB\db 目录下多了一些文件,这些文件就是数据库生成的。

MongoDB启动结果.png

在命令行连接数据库

打开命令行终端,执行以下命令即可连接到数据库:

$ mongo mongodb://127.0.0.1:3001
# 或者
$ mongo -port 3001

连接成功之后,可以看到如下图结果:

连接MongoDB.png

我们看到数据库是没有访问控制的,数据库的读写权限不受控制的。

MongoDB 用户创建、更新、删除

我们将启用 MongoDB 的用户访问控制,开启验证后,用户只能对数据库进行符合权限的操作。

关于 MongoDB 访问权限的设置这里有 详细介绍 ,接下来开始实战。

admin 数据库创建管理员

要使用访问控制,我们先确保有一个超级用户,这个用户在 admin 数据库里面创建,并且拥有 userAdmin 或者userAdminAnyDatabase 的权限,超级用户可以创建用户、授权或者删除用户权限、自定义权限。

admin 数据库则主要存储 MongoDB 的用户、角色等信息。

在前面的介绍中我们启动的数据库是没有开启访问控制的,不过即使这样,我们也可以在启动授权控制之前就创建超级用户,因为 MongoDB 提供了一个 localhost exception 来创建超级用户到 admin 数据库。

一旦超级用户被创建了,我们需要验证登录这个用户来创建更多用户,下面来看具体操作。

紧接之前实战,我们已经通过非授权的方式启动并连接到数据库,接下来就是创建超级用户:

> use admin
switched to db admin

上面的这个命令 use admin 能够切换到 admin 数据库,执行成功之后,我们就可以在 admin 数据库进行操作了。

那么首先来创建一个管理员用户,这个用户具有创建管理其他用户的权限:

> db.createUser(
   {
...     user: "admin",
...     pwd: "admin",
...     roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
...   }
... )

# 执行结果

Successfully added user: {
        "user" : "admin",
        "roles" : [
                {
                        "role" : "userAdminAnyDatabase",
                        "db" : "admin"
                }
        ]
}

上面的命令的 ··· 是换行,如果在命令行里面不能换行,可以整理成一行来执行。如:

> db.createUser( { user: "admin",pwd: "admin", roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]} )

这其中 user 指的是我们的用户名, pwd 是密码,而 roles 里面配置的正是这个用户的权限。userAdminAnyDatabase 就是一个具有在其他数据库增删和管理用户的权限,db 指定了创建的这个管理员用户所在的数据库是 admin

注意:超级用户可以访问所有数据库,这个用户是被创建在 admin 管理数据库,db 指定数据库。

启动数据库访问控制

之前的启动数据库的方式并不是访问控制的,我们删掉之前安装的 Windows service , 以管理员身份执行 sc delete koa-blog

# 执行 exit 退出数据库连接
> exit
bye

# 删掉service
$ sc delete koa-blog
[SC] DeleteService SUCCESS

接着启用权限控制,执行下面的命令,执行之前确保系统 MongoDB 进程关闭,这里使用的 --auth 是用来开启授权启动:

$ mongod --config "C:\MongoDB\mongod.cfg" --serviceName "koa-blog" --serviceDisplayName "koa-blog" --auth --install

$ net start koa-blog

可以看到这种启动方式比之前多了一个 --auth

在对应数据库创建用户

既然超级用户已经被我们创建好了(这个超级用户是在 admin 数据库),那么我们先连接数据库:

$ mongo -port 3001

为了测试在不验证用户的情况下是否能进行数据操作,我们先不登录这个超级用户,而是切换到一个数据库 koaBlog, 执行 use koaBlog 切换到 koaBlog 数据库。我们可以执行 db 查看当前的数据库。先来插入一条数据试试:

> db.koaBlog.insert({name:'Moyufed'})
插入数据.png

我们看到 “not authorized on koaBlog to execute command” ,这就是说, 我们没有权限操作。

不能插入数据正是我们想要的结果,但是为了能够在这个数据库插入数据,我们就需要去创建有权限的用户了,

因此我们切换到 admin 数据库去登录账号:

> use admin
switched to db admin
> db
admin
> db.auth("admin", "admin")
1 # 返回1 授权成功, 否则返回0, 并提示失败

上面的命令执行完毕之后,我们就登录了数据库。先来看看怎么创建用户:

使用 db.createUser() 添加用户,以及用户的 内置权限 或 用户定义权限 。

我们上面创建的 admin 用户只能 管理用户和权限,如果要执行其它操作,如从数据库中查询数据,MongoDB 会返回错误。
下面我们来为 koaBlog创建一个有 读写权限 的用户:

# 执行
> use koaBlog
switched to db koaBlog


# 执行
> db.createUser(
...   {
...     user: "moyufed",
...     pwd: "123456",
...     roles: [ { role: "readWrite", db: "koaBlog" } ]
...   }
... )

# 结果
Successfully added user: {
        "user" : "moyufed",
        "roles" : [
                {
                        "role" : "readWrite",
                        "db" : "koaBlog"
                }
        ]
}

上面的示例中,我们切换到 koaBlog 数据库上创建用户, 因为只有在这里创建的用户才是这个数据库的用户, 才能在这里完成授权。

但是需要注意的是,我们刚刚创建的这个用户的信息是存放在 admin 库中的,为了验证,我们接着换到 admin库,看一下刚刚创建的用户,首先切换到 admin 数据库肯定要先 use admin ,接着执行下面的命令查找用户:

> use admin
switched to db admin
> db.system.users.find({user:'moyufed'})
{ "_id" : "koaBlog.moyufed", "user" : "moyufed", "db" : "koaBlog", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "dc1TCbvsO20LgyX0UsxoXg==", "storedKey" : "FQmO72ZNFkt9MSvH+5gZ6fd9h5M=", "serverKey" : "Oz0XFo+fne8sTS3yhXzYp3i942k=" } }, "roles" : [ { "role" : "readWrite", "db" : "koaBlog" } ] }
>

使用创建的用户来新增数据

我们现在用新增的用户来连接数据库,下面的命令演示不同的方式启动和连接数据库,在连接数据库时就进行验证,和前面的 admin 用户登录的方式效果一样,前面的方式是先连接数据库再验证:

# 先退出连接
> exit
bye

# 重新连接数据库
$ mongo --port 3001 -u moyufed -p 123456 --authenticationDatabase koaBlog
MongoDB shell version v3.4.5
connecting to: mongodb://127.0.0.1:3001/
MongoDB server version: 3.4.5
>

既然已经验证成功,我们就可以尝试着来写入数据了,首先还是要切换到 koaBlog 数据库(我们的用户是在这个数据库创建的),接着我们来执行插入数据。

> use koaBlog
switched to db koaBlog
> db.koaBlog.insert({name:'Moyufed'})
WriteResult({ "nInserted" : 1 })
>

OK!我们已经能正常写入数据了。

注意:登录一个用户的时候,要切换到与该用户对应的数据库,而用户是储存在 admin 数据库的

参数说明

参数 描述
--bind_ip 绑定服务IP,若绑定127.0.0.1,则只能本机访问,不指定默认本地所有IP
--logpath 定 MongoDB 日志文件,注意是指定文件不是目录
--logappend 使用追加的方式写日志
--dbpath 指定数据库路径
--port 指定服务端口号,默认端口 27017
--serviceName 指定服务名称
--serviceDisplayName 指定服务名称,有多个 mongodb 服务时执行。
--install 指定作为一个 Windows 服务安装。

权限说明

分类 role(角色) 简要说明
数据库用户角色(DB User Roles) read readWrite 为某个数据库创建一个用户, 分配该数据库的读写权力
数据库管理员角色(DB Admin Roles) dbAdmin dbOwner userAdmin 拥有创建数据库, 和创建用户的权力
集群管理角色(Culster Administration Roles) clusterAdmin clusterManager clusterMonitor hostManager 管理员组, 针对整个系统进行管理
备份还原角色(Backup and Restoration Roles) backup restore 备份数据库, 还原数据库
所有数据库角色(All-Database Roles) readAnyDatabase readWriteAnyDatabase``userAdminAnyDatabase``dbAdminAnyDatabase 拥有对admin操作的权限
Superuser Roles(超级管理员) root dbOwner userAdmin userAdminAnyDatabase这几个角色角色提供了任何数据任何用户的任何权限的能力,拥有这个角色的用户可以在任何数据库上定义它们自己的权限

修改用户角色

更新用户

> db.updateUser([用户名],{用户对象, 与创建时一样})  # 后面还有一个可选参数writeConcern, 一般不写

创建用户时和更新用户都需要属性user pwd roles成功修改后没有任何提示. 如下:

# 修改密码并且修改角色为只读
> db.updateUser('test',{user:'test',pwd:'admin',roles:[{role:'read',db:'testDB'}]})
>

以上需要注意的就是, roles数组里的对象数据role db两个都需要给出, 否则会出现错误

删除用户

> use testDB
switched to db testDB
> db.dropUser('test')
true
>

总结

  • 一定切换到对应的数据库去创建用户, 否则在进行认证的时候, 会提示找不到用户。
  • 一定要到对应的数据库上去认证用户,否则会认证授权失败。
  • 不是所有人都能操作 admin 数据库, 分配给用户权限的时候,一定要谨慎。
  • 修改用户和删除用户都和创建用户一样,需要切换到数据库管理员的身份。也就是需要先切换到admin库完成认证才能进行后面的操作,同样需要到对应数据库去操作用户, 因为用户是跟着库走的。

参考资料

Why am I getting a parser error on my YAML config in MongoDB --Install

Enable Access Control

经过本节实战,我们安装和配置好了 MongoDB ,下一步,我们来了解项目的环境配置…

推荐阅读更多精彩内容