# mongodb 安全认证


<!--more-->


## 1. 安全认证概述

MongoDB默认是没有账号的，可以直接连接，无须身份验证。实际项目中肯定是要权限验证的，否则后果不堪设想。从2016年开始发生了多起MongoDB黑客赎金事件，大部分MongoDB安全问题暴露出了安全问题的短板其实是用户，首先用户对于数据库的安全不重视，其次用户在使用过程中可能没有养成定期备份的好习惯，最后是企业可能缺乏有经验和技术的专业人员。所以对MongoDB进行安全认证是必须要做的。

## 2. 用户相关操作

### 2.1 切换到admin数据库对用户的添加

```
use admin;
db.createUser(USER_DOCUMENT): 用于创建创建登录用户及分配权限的方法
例:
db.createUser(
	{
		user:"账号",
		pwd:"密码",
		roles:[
			{role:"角色",db:"安全认证的的数据库"},
			{role:"角色",db:"安全认证的的数据库"}
		]
	}
)
```

- user：创建的用户名称，如 admin、root 、lagou

- pwd：用户登录的密码

- roles：为用户分配的角色，不同的角色拥有不同的权限，参数是数组，可以同时设置多个

- role：角色，MonngoDB 已经约定好的角色，不同的角色对应不同的权限 后面会对role做详细解释

- db：数据库实例名称，如 MongoDB 4.0.2 默认自带的有 admin、local、confifig、test 等，即为哪个数据库实例设置用户

```
例: 
db.createUser( {user:"root", pwd:"123321", roles:[{role:"root",db:"admin"}] }) //root用户只能在admin下创建
```

### 2.2 修改密码

```
db.changeUserPassword( 'root' , 'rootNew' );
```

### 2.3 用户添加角色

```
db.grantRolesToUser( '用户名' , [{ role: '角色名' , db: '数据库名'}])
```

### 2.4 以auth方式启动mongod

```
./bin/mongod -f conf/mongo.conf --auth
（也可以在mongo.conf 中添加auth=true 参数）
```

### 2.5 验证用户

```
db.auth("账号","密码")
```

### 2.6 删除用户

```
db.dropUser("用户名")
```



## 3. 角色

### 3.1 数据库内置的角色

```
read：允许用户读取指定数据库 
readWrite：允许用户读写指定数据库 
dbAdmin：允许用户在指定数据库中执行管理函数，如索引创建、删除，查看统计或访问 system.profile 
userAdmin：允许用户向system.users集合写入，可以找指定数据库里创建、删除和管理用户 
clusterAdmin：只在admin数据库中可用，赋予用户所有分片和复制集相关函数的管理权限 
readAnyDatabase：只在admin数据库中可用，赋予用户所有数据库的读权限 
readWriteAnyDatabase：只在admin数据库中可用，赋予用户所有数据库的读写权限 
userAdminAnyDatabase：只在admin数据库中可用，赋予用户所有数据库的userAdmin权限 
dbAdminAnyDatabase：只在admin数据库中可用，赋予用户所有数据库的dbAdmin权限 
root：只在admin数据库中可用。超级账号，超级权限 
dbOwner：库拥有者权限，即readWrite、dbAdmin、userAdmin角色的合体
```

### 3.2 各个类型用户对应角色

```
数据库用户角色：read、readWrite 
数据库管理角色：dbAdmin、dbOwner、userAdmin 
集群管理角色：clusterAdmin、clusterManager、clusterMonitor、hostManager 
备份恢复角色：backup、restore； 
所有数据库角色：readAnyDatabase、readWriteAnyDatabase、
						userAdminAnyDatabase、 dbAdminAnyDatabase 
超级用户角色：root 这里还有几个角色间接或直接提供了系统超级用户的访问（
						dbOwner 、userAdmin、 userAdminAnyDatabase）
```

## 4. 单机安全认证实现流程

案例: 创建 mydb1 数据库并创建了两个用户，zhangsan 拥有读写权限，lisi 拥有只读权限测试这两个账户的权限。

- 创建管理员

  MongoDB 服务端开启安全检查之前，至少需要有一个管理员账号，admin 数据库中的用户都被视为管理员

  如果 admin 库没有任何用户的话，即使在其他数据库中创建了用户，启用身份验证，默认的连接方式依然会有超级权限，即仍然可以不验证账号密码照样能进行 CRUD，安全认证相当于无效。

  ```
  use admin;
  > db;//查看当前db
  admin
  > db.createUser( 
   { 
    user:"root", 
    pwd:"123456", 
    roles:[{role:"root",db:"admin"}] 
   })
  ```

- 创建普通用户

  如下所示 mydb1 是自己新建的数据库，没安全认证之前可以随意 CRUD，其余的都是 mongoDB4.0.2 自带的数据库

  ```
  >show dbs 
  admin 0.000GB 
  config 0.000GB 
  local 0.000GB 
  mydb1 0.000GB
  
  > use mydb1 
  switched to db mydb1 
  > db.c1.insert({name:"testdb1"}) 
  > db.c1.insert({name:"testdb1"}) 
  > show tables 
  c1
  c2
  
  > db.c1.find()
  ```

  - 为 admin 库创建管理员之后，现在来为 普通数据库创建普通用户，以 mydb1 为例，方式与创建管理员一致，切换到指定数据库进行创建即可

  - 如下所示，为 mydb1 数据库创建了两个用户，zhangsan 拥有读写权限，lisi 拥有只读权限，密码都是 123456.

    ```
    use mydb1 
    switched to db mydb1 
    
    > db 
    mydb1 
    
    > db.createUser({ 
      user:"zhangsan", 
      pwd:"123456", 
      roles:[{role:"readWrite",db:"mydb1"}] 
     }) 
    
    > db.createUser({ 
      user:"lisi", 
      pwd:"123456", 
      roles:[{role:"read",db:"mydb1"}] 
     })
    ```

  - 接着从客户端关闭 MongoDB 服务端，之后服务端会以安全认证方式进行启动

    ```
    > use admin 
    switched to db admin 
    
    > db.shutdownServer() 
    server should be down...
    ```

- mongodb安全认证方式启动

  mongod --dbpath=数据库路径 --port=端口 --auth

  也可以在配置文件中 加入 auth=true

- 分别以普通用户登录验证权限

  普通用户现在仍然像以前一样进行登录，如下所示直接登录进入 mydb1 数据库中，登录是成功的，只是登录后日志少了很多东西，而且执行 show dbs 命令，以及 show tables 等命令都是失败的，即使没有被安全认证的数据库，用户同样操作不了，这都是因为权限不足，一句话：用户只能在自己权限范围内的数据库中进行操作

  如下所示，登录之后必须使用 db.auth("账号","密码") 方法进行安全认证，认证通过，才能进行权限范围内的操作

  ```
  > db.auth("zhangsan","123456") 
  1
  
  > show dbs 
  mydb1 0.000GB 
  
  > show tables 
  c1
  c2
  ```

- 以管理员登录验证权限

  客户端管理员登录如下所示 管理员 root 登录，安全认证通过后，拥有对所有数据库的所有权限。



## 5. 分片集群安全认证

### 5.1 开启安全认证前,先去"路由"创建管理员和普通用户

参考前面单机即可

### 5.2 关闭所有的配置节点/分片节点/路由节点

```
安装psmisc 
yum install psmisc 

安装完之后可以使用killall 命令 快速关闭多个进程 
killall mongod
```

### 5.3 生成密钥文件并修改权限

```shell
openssl rand -base64 756 > data/mongodb/testKeyFile.file 

#授权
chmod 600 data/mongodb/keyfile/testKeyFile.file
```

### 5.4 配置节点集群和分片节点集群开启安全认证和指定密钥文件

```
auth=true 
keyFile=/data/mongodb/testKeyFile.file
```

### 5.5 在路由配置文件中设置密钥文件

```
keyFile=/data/mongodb/testKeyFile.file
```

### 5.6 启动所有的节点,使用路由进行权限验证

可以编写一个启动脚本 start.sh

```sh
./bin/mongod -f config/config-17017.conf 
./bin/mongod -f config/config-17018.conf 
./bin/mongod -f config/config-17019.conf
./bin/mongod -f shard1/shard1-37017.conf 
./bin/mongod -f shard1/shard1-37018.conf 
./bin/mongod -f shard1/shard1-37019.conf 
./bin/mongod -f shard2/shard2-47017.conf 
./bin/mongod -f shard2/shard2-47018.conf 
./bin/mongod -f shard2/shard2-47019.conf
./bin/mongos -f router/router-27017.conf
```

### 5.7 使用root和我们刚创建的普通用户zhangsan连接测试

使用客户端

或

springboot

```
spring.data.mongodb.username=账号 
spring.data.mongodb.password=密码 
#spring.data.mongodb.uri=mongodb://账号:密码@IP:端口/数据库名
```




