MongoDB SCRAM身份验证机制详解
MongoDB 数据库中的 Salted 质询响应身份验证机制(Salted Challenge Response Authentication Mechanism,SCRAM)是 MongoDB 默认的身份验证机制。当用户进行身份验证时,MongoDB 会使用 SCRAM 针对用户的 name、password 和 authentication database 来验证所提供的用户凭证。
SCRAM 基于 IETF RFC 5802 标准,该标准定义了实现质询响应机制以使用密码对用户进行身份验证的最佳实践。MongoDB 的 SCRAM 实现提供了以下功能:
MongoDB 数据库支持的 SCRAM 机制如下表所示:
创建或更新 SCRAM 用户时,可以指定如下内容:
如果使用 SCRAM-SHA-256,MongoDB 需要服务器端密码哈希,这意味着服务器会对密码进行摘要处理。如果使用 SCRAM-SHA-1,MD5 是有必要使用的,但并不用于加密目的。如果使用的是 FIPS 模式,则不使用 SCRAM-SHA-1,而是使用 SCRAM-SHA-256、Kerberos、LDAP 或 x.509。
这里补充说明一下,当 mongod 启动时,会在数据目录路径(/var/lib/mongodb)中创建一些系统文件。为了确保系统文件具有正确的所有权,需要以 mongod 用户身份登录。如果以 root 用户身份启动 mongod,则必须稍后更新文件所有权。
一般情况下,userAdminAnyDatabase 角色允许用户进行如下操作:
另外,可以根据需要为用户分配其他内置角色或用户自定义角色。创建该用户的数据库即为该用户的身份验证数据库。虽然该用户需要通过此数据库进行身份验证,但该用户还可能会在其他数据库中拥有角色。同时,该用户的身份验证数据库不会限制该用户的特权。
在启用访问控制的情况下启动 mongod,如果在命令行中启动 mongod,则需要添加 --auth 命令行选项:
如果使用配置文件启动 mongod,则添加以下 security.authorization 配置文件设置:
① 在连接期间进行身份验证。使用 -u <username>、-p 和 --authenticationDatabase <database> 命令行选项启动 mongosh,具体命令如下:
② 在连接后进行身份验证。使用 mongosh 连接到数据库部署:
SCRAM 基于 IETF RFC 5802 标准,该标准定义了实现质询响应机制以使用密码对用户进行身份验证的最佳实践。MongoDB 的 SCRAM 实现提供了以下功能:
- 可调工作因子(迭代计数);
- 每个用户的随机盐;
- 服务器和客户端之间的双向身份验证。
MongoDB 数据库支持的 SCRAM 机制如下表所示:
SCRAM 机制 | 说明 |
---|---|
SCRAM-SHA-1 |
使用 SHA-1 哈希函数 要修改 SCRAM-SHA-1 的迭代计数 |
SCRAM-SHA-256 |
使用 SHA-256 哈希函数 要修改 SCRAM-SHA-256 的迭代计数 |
创建或更新 SCRAM 用户时,可以指定如下内容:
- 要使用的 SCRAM 机制;
- 对密码进行摘要处理的是服务器还是客户端。
如果使用 SCRAM-SHA-256,MongoDB 需要服务器端密码哈希,这意味着服务器会对密码进行摘要处理。如果使用 SCRAM-SHA-1,MD5 是有必要使用的,但并不用于加密目的。如果使用的是 FIPS 模式,则不使用 SCRAM-SHA-1,而是使用 SCRAM-SHA-256、Kerberos、LDAP 或 x.509。
使用SCRAM对客户端进行身份验证
在独立运行的 mongod 实例上进行客户端身份验证,设置 SCRAM 的步骤如下:1) 在没有访问控制的情况下启动MongoDB
在没有访问控制的情况下,启动独立运行的 mongod 实例,打开终端并以 mongod 用户的身份运行以下命令:mongod --port 27017 --dbpath /var/lib/mongodb上面代码中使用的端口(port 27017)和数据目录路径(/var/lib/mongodb)只是具体的示例。设计人员可以根据自己的实际项目需求进行指定。
这里补充说明一下,当 mongod 启动时,会在数据目录路径(/var/lib/mongodb)中创建一些系统文件。为了确保系统文件具有正确的所有权,需要以 mongod 用户身份登录。如果以 root 用户身份启动 mongod,则必须稍后更新文件所有权。
2) 连接到实例
打开新终端并使用 mongosh 连接到集群,具体命令如下:mongosh --port 27017如要连接到其他部署,可根据需要指定 --host 等其他命令行选项进行连接。
3) 创建用户管理员
使用 mongosh 切换到 admin 数据库,添加具有 userAdminAnyDatabase 和 readWriteAnyDatabase 角色的 myUserAdmin 用户,具体命令如下:use admin db.createUser( { user: "myUserAdmin", pwd: passwordPrompt(), // or cleartext password roles: [ { role: "userAdminAnyDatabase", db: "admin" }, { role: "readWriteAnyDatabase", db: "admin" } ] } )在上述代码中,passwordPrompt() 方法会提示输入密码,在使用时也可以直接将密码指定为字符串。这里建议使用 passwordPrompt() 方法,可以避免将密码显示在屏幕上,同时避免将密码泄露到 Shell 历史记录中。
一般情况下,userAdminAnyDatabase 角色允许用户进行如下操作:
- 创建用户;
- 授予或撤销用户的角色;
- 创建或修改自定义角色。
另外,可以根据需要为用户分配其他内置角色或用户自定义角色。创建该用户的数据库即为该用户的身份验证数据库。虽然该用户需要通过此数据库进行身份验证,但该用户还可能会在其他数据库中拥有角色。同时,该用户的身份验证数据库不会限制该用户的特权。
4) 使用访问控制重新启动MongoDB实例
关闭 mongod 实例,使用 mongosh 发出以下命令:db.adminCommand({ shutdown: 1 })然后,退出 mongosh 命令行。
在启用访问控制的情况下启动 mongod,如果在命令行中启动 mongod,则需要添加 --auth 命令行选项:
mongod --auth --port 27017 --dbpath /var/lib/mongodb
如果使用配置文件启动 mongod,则添加以下 security.authorization 配置文件设置:
security: authorization: enabled连接到此实例的客户端现在必须对自身进行身份验证,并且只能执行由所分配角色确定的操作。
5) 连接并认证为用户管理员
使用 mongosh 即可进行身份验证,包括在连接期间进行身份验证和在连接后进行身份验证两种情形。① 在连接期间进行身份验证。使用 -u <username>、-p 和 --authenticationDatabase <database> 命令行选项启动 mongosh,具体命令如下:
mongosh --port 27017 --authenticationDatabase "admin" -u "myUserAdmin" -p然后,根据提示输入密码。
② 在连接后进行身份验证。使用 mongosh 连接到数据库部署:
mongosh --port 27017在 mongosh 中,切换到身份验证数据库,并使用 db.auth(<username>, <pwd>) 方法进行身份验证:
use admin db.auth("myUserAdmin", passwordPrompt()) // or cleartext password然后,根据提示输入密码。