MongoDB 安全认证

一、MongoDB 的用户和角色权限介绍

        默认情况下,MongoDB 实例启动运行时是没有启用用户访问权限控制的,也就是说,在实例本机服务器上都可以随意连接到实例进行各种操作,MongoDB 不会对连接客户端进行用户验证,这是非常危险的。

        mongodb 官网上说,为了能保障 mongodb 的安全可以做以下几个步骤:

        1):使用新的端口,默认的 27017 端口如果一旦知道了 ip 就能连接上,不太安全。

        2):设置 mongodb 的网络环境,最好将 mongodb 部署到公司服务器内网,这样外网是访问不到的。公司内部访问使用 vpn 等。

        3):开启安全认证。认证要同时设置服务器之间的内部认证方式,同时要设置客户端连接到集群的账号密码认证方式。

        为了强制开启用户访问控制(用户验证),则需要在 MongoDB 实例启动时使用选项 --auth 或在指定启动配置文件中添加选项 auth=true 。在开始之前需要了解一下概念。

启用访问控制

        MongoDB 使用的是基于角色的访问控制(Role-Based Access Control,RBAC)来管理用户对实例的访问。通过对用户授予一个或多个角色来控制用户访问数据库资源的权限和数据库操作的权限,在对用户分配角色之前,用户无法访问实例。

        在实例启动时添加选项 --auth 或指定启动配置文件中添加选项 auth=true

角色

        在 MongoDB 中通过角色对用户授予相应数据库资源的操作权限,每个角色当中的权限可以显式指定,也可以通过继承其他角色的权限,或者两都都存在的权限。

权限

        权限由指定的数据库资源(resource)以及允许在指定资源上进行的操作(action)组成。

        1、资源(resource)包括:数据库、集合、部分集合和集群;

        2.、操作(action)包括:对资源进行的增、删、改、查(CRUD)操作。

        在角色定义时可以包含一个或多个已存在的角色,新创建的角色会继承包含的角色所有的权限。在同一个数据库中,新创建角色可以继承其他角色的权限,在 admin 数据库中创建的角色可以继承在其它任意数据库中角色的权限。

# 查询所有角色权限(仅用户自定义角色)
db.runCommand({ rolesInfo: 1 })

# 查询所有角色权限(包含内置角色)
db.runCommand({ rolesInfo: 1, showBuiltinRoles: true })

# 查询当前数据库中的某角色的权限
db.runCommand({ rolesInfo: "<rolename>" })

# 查询其它数据库中指定的角色权限
db.runCommand({ rolesInfo: { role: "<rolename>", db: "<database>" } }

# 查询多个角色权限
db.runCommand(
    {
        rolesInfo: [
            "<rolename>",
            { role: "<rolename>", db: "<database>" },
            ...
        ]
    }
)

        示例,查看所有的内置角色:

myshardrs01:PRIMARY> db.runCommand({rolesInfo:1,showBuiltinRoles:true})
{
	"roles" : [
		{
			"role" : "dbAdmin",
			"db" : "articledb",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "dbOwner",
			"db" : "articledb",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "enableSharding",
			"db" : "articledb",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "read",
			"db" : "articledb",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "readWrite",
			"db" : "articledb",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		},
		{
			"role" : "userAdmin",
			"db" : "articledb",
			"isBuiltin" : true,
			"roles" : [ ],
			"inheritedRoles" : [ ]
		}
	],
	"ok" : 1,
	"operationTime" : Timestamp(1697524734, 1),
	"$gleStats" : {
		"lastOpTime" : Timestamp(0, 0),
		"electionId" : ObjectId("7fffffff0000000000000003")
	},
	"lastCommittedOpTime" : Timestamp(1697524734, 1),
	"$configServerState" : {
		"opTime" : {
			"ts" : Timestamp(1697524736, 3),
			"t" : NumberLong(4)
		}
	},
	"$clusterTime" : {
		"clusterTime" : Timestamp(1697524736, 3),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}

常用的内置角色:

        数据库用户角色:readreadWrite

        所有数据库用户角色:readAnyDatabasereadWriteAnyDatabaseuserAdminAnyDatabasedbAdminAnyDatabase

        数据库管理角色:dbAdmindbOwneruserAdmin

        集群管理角色:clusterAdminclusterManagerclusterMonitorhostManager

        备份恢复角色:backuprestore

        超级用户角色:root

        内部角色:system

角色
权限描述
read
可以读取指定数据库中任何数据。
readWrite
可以读写指定数据库中任何数据,包括创建、重命名、删除集合。
readAnyDatabase
可以读取所有数据库中任何数据( 除了数据库  config  和  local  之外)
readWriteAnyDatabase
可以读取所有数据库中任何数据(除了数据库 config 和 local 之外)
userAdminAnyDatabase
可以在指定数据库创建和修改用户( 除了数据库  config  和  local  之外)
dbAdminAnyDatabase
可以读取任何数据库以及对数据库进行清理、修改、压缩、获取统计信息、执行检查等操作(除了数据库 config 和 local 之外)。
dbAdmin
可以读取指定数据库以及对数据库进行清理、修改、压缩、获取统计信息、执行检查等操作。
userAdmin
可以在指定数据库创建和修改用户。
clusterAdmin
可以对整个集群或数据库系统进行管理操作。
backup
备份  MongoDB  数据最小的权限。
restore
从备份文件中还原恢复 MongoDB 数据(除了 system.profile 集合)的权限。
root
超级账号,超级权限

二、单实例环境

        目标:对单实例的 MongoDB 服务开启安全认证,这里的单实例指的是未开启副本集或分片的 MongoDB 实例。

2.1 关闭已开启的服务

        增加 mongod 的单实例的安全认证功能,可以在服务搭建的时候直接添加,也可以在之前搭建好的服务上添加。

        本文使用之前搭建好的服务,因此,先停止之前的服务停止服务的方式有两种:快速关闭和标准关闭,下面依次说明:

1):快速关闭方法

        快速,简单,数据可能出错。通过系统的 kill 命令直接杀死进程。杀完要检查一下,避免有的没有杀掉。

# 通过进程编号关闭节点
kill -2 54410

        如果一旦是因为数据损坏,则需要进行如下操作:

# 删除 lock 文件
rm -f /mongodb/single/data/db/*.lock

# 修复数据
/usr/local/mongodb/bin/mongod --repair --dbpath=/mongodb/single/data/db

2):标准的关闭方法

        数据不容易出错,但是麻烦。通过 mongo 客户端中的 shutdownServer 命令来关闭服务,如下:

# 客户端登录服务,注意,这里通过 localhost 登录,如果需要远程登录,必须先登录认证才行。
mongo --port 27017

# 切换到admin库
use admin

# 关闭服务
db.shutdownServer()

2.2 添加用户和权限

        先按照普通无授权认证的配置,启动我们之前配置过的 mongo 服务,命令如下:

# 此时是未开启认证的方式来启动 MongoDB 服务
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/single/mongod.conf
# 使用客户端进行连接
/usr/local/mongodb/bin/mongo --host 192.168.229.154 --port 27017

        创建两个管理员用户,一个是系统的超级管理员 myroot ,一个是 admin 库的管理用户 myadmin,命令如下:

# 切换到 admin 库
> use admin
switched to db admin

# 创建系统超级用户 myroot,设置密码 123456,设置角色 root
# 完整的语法是这个:db.createUser({user:"myroot",pwd:"123456",roles:[ { "role" : "root", "db" :"admin" } ]}),下面可以简写
> db.createUser({user:"myroot",pwd:"123456",roles:["root"]})
Successfully added user: { "user" : "myroot", "roles" : [ "root" ] }

# 创建专门用来管理 admin 库的账号 myadmin,只用来作为用户权限的管理
> db.createUser({user:"myadmin",pwd:"123456",roles:[{role:"userAdminAnyDatabase",db:"admin"}]})
Successfully added user: {
	"user" : "myadmin",
	"roles" : [
		{
			"role" : "userAdminAnyDatabase",
			"db" : "admin"
		}
	]
}

# 查看已经创建了的用户的情况
> db.system.users.find()
{ "_id" : "admin.myroot", "userId" : UUID("9d68a377-de4a-473e-876b-8ea02e391559"), "user" : "myroot", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "UNX9oZ7Il7q0i+mBw4i9Kg==", "storedKey" : "UZp8+t7G47vl4vVX6CxEuhiAH+s=", "serverKey" : "UlV8YY5RGVJEeNuwe0YekNDGBts=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "91hfmuv7gG/69F0whyOUJiMh4aODF7cSa5DyUg==", "storedKey" : "9ny/JIyBZQIw9Qout+ccFXI0zecMc2k9KsHATGh2oZw=", "serverKey" : "3W4mNSX10wdR0fJhCGESdEugtXMWPOzCmlh+S6iZWl8=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
{ "_id" : "admin.myadmin", "userId" : UUID("1e19cebb-1eb7-49a1-84da-b10d66db1b58"), "user" : "myadmin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "3ZSJLMjO10S1cXSLD/1pGQ==", "storedKey" : "1r+jQsk1QV2hpSuMKygraEDxH7k=", "serverKey" : "WR70/Kdb5ZRlpbElA8r//ENAWzU=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "yIXKOH7pF+DZBYe8kzR6C1gyDFEW74+dmDLTKg==", "storedKey" : "qEFZoLeP+8O0fMdNtSxv9mR2I75to2dwh7IL+O1o7AY=", "serverKey" : "R2wK0XOCKLLutU7GQe7U7WRRCL3MyxqqmrboatKS1N0=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }

# 删除用户
>  db.dropUser("myadmin")
true

# # 查看已经创建了的用户的情况
> db.system.users.find()
{ "_id" : "admin.myroot", "userId" : UUID("9d68a377-de4a-473e-876b-8ea02e391559"), "user" : "myroot", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "UNX9oZ7Il7q0i+mBw4i9Kg==", "storedKey" : "UZp8+t7G47vl4vVX6CxEuhiAH+s=", "serverKey" : "UlV8YY5RGVJEeNuwe0YekNDGBts=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "91hfmuv7gG/69F0whyOUJiMh4aODF7cSa5DyUg==", "storedKey" : "9ny/JIyBZQIw9Qout+ccFXI0zecMc2k9KsHATGh2oZw=", "serverKey" : "3W4mNSX10wdR0fJhCGESdEugtXMWPOzCmlh+S6iZWl8=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }

# //修改密码
> db.changeUserPassword("myroot", "123456")

提示:

        1、本案例创建了两个用户,分别对应超管和专门用来管理用户的角色,事实上,你只需要一个用户即可。如果你对安全要求很高,防止超管泄漏,则不要创建超管用户。

        2、和其它数据库(MySQL)一样,权限的管理都差不多一样,也是将用户和权限信息保存到数据库对应的表中。Mongodb 存储所有的用户信息在 admin 数据库的集合 system.users 中,保存用户名、密码和数据库信息。

        3、如果不指定数据库,则创建的指定的权限的用户在所有的数据库上有效,如 {role:"userAdminAnyDatabase", db:""}

        认证测试,测试添加的用户是否正确,如下:

# 切换到 admin
> use admin
switched to db admin

# 密码输错
> db.auth("myroot","12345")
Error: Authentication failed.
0

# 密码正确
> db.auth("myroot","123456")
1

        创建普通用户可以在没有开启认证的时候添加,也可以在开启认证之后添加,但开启认证之后,必须使用有操作 admin 库的用户登录认证后才能操作。底层都是将用户信息保存在了 admin 数据库的集合 system.users 中。

# 切换将来要操作的数据库 articledb
> use articledb
switched to db articledb

# 创建用户,拥有 articledb 数据库的读写权限 readWrite,密码是 123456
> db.createUser({user: "bobo", pwd: "123456", roles: [{ role: "readWrite", db:"articledb" }]})
Successfully added user: {
	"user" : "bobo",
	"roles" : [
		{
			"role" : "readWrite",
			"db" : "articledb"
		}
	]
}

# 测试是否可用
> db.auth("bobo","123456")
1

        如果开启了认证后,登录的客户端的用户必须使用 admin 库的角色,如拥有 root 角色的 myadmin 用户,再通过 myadmin 用户去创建其他角色的用户。

2.3 服务端开启认证和客户端连接登录

2.3.1 以开启认证的方式启动服务

        首先,关闭我们的 mongodb 服务,然后使用认证的方式启动服务,有两种方式开启权限认证启动服务:一种是参数方式,一种是配置文件方式。

参数方式:

# 在启动时指定参数 --auth
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/single/mongod.conf --auth

配置文件方式:

        修改 mongod.conf 配置文件

vim /usr/local/mongodb/single/mongod.conf

        添加下面的内容 

security:
  # 开启授权认证
  authorization: enabled
# 在启动时不用指定参数
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/single/mongod.conf

2.3.2 开启认证的情况下客户端登录

        有两种认证方式,一种是先登录,在 mongo shell 中认证;一种是登录时直接认证。

先连接后认证

# 启用客户端连接
[root@node1 ~]# /usr/local/mongodb/bin/mongo --host 192.168.229.154 --port 27017
MongoDB shell version v4.0.28
connecting to: mongodb://192.168.229.154:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("4a4dfb07-a0a6-4a29-ab65-bae36185baa7") }
MongoDB server version: 4.0.28

# 切换到 admin 库
> use admin
switched to db admin

# 查看 system.users 集合的用户
> db.system.users.find()
Error: error: {
	"ok" : 0,
	"errmsg" : "command find requires authentication",
	"code" : 13,
	"codeName" : "Unauthorized"
}

# 开启认证
> db.auth("myroot","123456")
1

# 才可以正常查询
> db.system.users.find()
{ "_id" : "admin.myroot", "userId" : UUID("9d68a377-de4a-473e-876b-8ea02e391559"), "user" : "myroot", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "L4DRjpZ1hGYS9ocr8MJHPg==", "storedKey" : "T/RE4CUOidZUw6iBR497kQyuvD0=", "serverKey" : "auPBWoCrhHUwGPFNo+5nmdezKrM=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "HK9NuONsh2SgFiYWVGhW30lVWh1CnqE1AyVHHQ==", "storedKey" : "gThP/LBsfcHXmnyqAgahFUwuYMyi+GKuEgUK9imvcHw=", "serverKey" : "2go3OncghbQdMruMy6N+KUWJAQGXWzXTAcF/Hk8Vnhs=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
{ "_id" : "articledb.bobo", "userId" : UUID("d688cc58-08b5-4b64-9fb9-138c1d75f814"), "user" : "bobo", "db" : "articledb", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "hsl6ms9Z8kQrb+OMiQBz3w==", "storedKey" : "y5zVIQZk3QsLtVMMfs0j+v78bEM=", "serverKey" : "F3Z2b4dSfKHvddA+e+efPgsZY1A=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "jtGEspSthcCD8NK41vffGFNQVLA+ySiOm4MErA==", "storedKey" : "QmFjxmRDK4LuAhKKY33orvD9MgxVzk+BBMXtbToyJLU=", "serverKey" : "oGqnQAZGFVerUHLpEvorFvvB1Vvkrxq9QqiXtmA8q1Y=" } }, "roles" : [ { "role" : "readWrite", "db" : "articledb" } ] }

        查询 articledb 库中的 comment 集合的内容,此时需要退出客户端然后重新的进行连接。

# 切换到 articledb 库
> use articledb
switched to db articledb

# 查看 comment 里面的数据,发现没有权限
> db.comment.find()
Error: error: {
	"ok" : 0,
	"errmsg" : "command find requires authentication",
	"code" : 13,
	"codeName" : "Unauthorized"
}

# 使用 bobo 账号登录
> db.auth("bobo","123456")
1

# 有查询的权限了
> db.comment.find()
{ "_id" : "1", "articleid" : "100001", "content" : "我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。", "userid" : "1002", "nickname" : "相忘于江湖", "createdatetime" : ISODate("2019-08-05T22:08:15.522Z"), "likenum" : 1000, "state" : "1", "parentid" : "3" }
{ "_id" : "2", "articleid" : "100001", "content" : "我夏天空腹喝凉开水,冬天喝温开水", "userid" : "1005", "nickname" : "伊人憔悴", "createdatetime" : ISODate("2019-08-05T23:58:51.485Z"), "likenum" : 888, "state" : "1", "parentid" : "3" }
{ "_id" : "3", "articleid" : "100001", "content" : "我一直喝凉开水,冬天夏天都喝。", "userid" : "1004", "nickname" : "杰克船长", "createdatetime" : ISODate("2019-08-06T01:05:06.321Z"), "likenum" : NumberLong(667), "state" : "1", "parentid" : "3" }
{ "_id" : "4", "articleid" : "100001", "content" : "专家说不能空腹吃饭,影响健康。", "userid" : "1003", "nickname" : "凯撒", "createdatetime" : ISODate("2019-08-06T08:18:35.288Z"), "likenum" : NumberLong(2001), "state" : "1", "parentid" : "3" }
{ "_id" : "5", "articleid" : "100001", "content" : "研究表明,刚烧开的水千万不能喝,因为烫嘴。", "userid" : "1003", "nickname" : "凯撒", "createdatetime" : ISODate("2019-08-06T11:01:02.521Z"), "likenum" : 3000, "state" : "1" }
{ "_id" : ObjectId("6527b60dcde6f61a6e8eeb59"), "content" : "测试添加的数据", "userid" : "1003", "nickname" : "凯撒大帝", "createdatetime" : ISODate("2023-10-12T09:02:05.315Z"), "likenum" : 0, "replynum" : 0, "state" : "1", "articleid" : "100000", "_class" : "cn.article.po.Comment" }

登录时直接认证

        ​​​​​​​admin 数据库进行登录认证和相关操作,如下:

# 直接进行登录
[root@node1 ~]# /usr/local/mongodb/bin/mongo --host 192.168.229.154 --port 27017 --authenticationDatabase admin -u myroot -p 123456
MongoDB shell version v4.0.28
connecting to: mongodb://192.168.229.154:27017/?authSource=admin&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("370e6621-2045-4801-bbc6-998952f34709") }
MongoDB server version: 4.0.28
Server has startup warnings: 
2023-10-17T00:44:30.596-0700 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2023-10-17T00:44:30.596-0700 I CONTROL  [initandlisten] 
2023-10-17T00:44:30.596-0700 I CONTROL  [initandlisten] 
2023-10-17T00:44:30.597-0700 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2023-10-17T00:44:30.597-0700 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2023-10-17T00:44:30.597-0700 I CONTROL  [initandlisten] 
2023-10-17T00:44:30.597-0700 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2023-10-17T00:44:30.597-0700 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2023-10-17T00:44:30.597-0700 I CONTROL  [initandlisten] 
---
Enable MongoDB is free cloud-based monitoring service, which will then receive and display
metrics about your deployment (disk utilization, CPU, operation statistics, etc).

The monitoring data will be available on a MongoDB website with a unique URL accessible to you
and anyone you share the URL with. MongoDB may use this information to make product
improvements and to suggest MongoDB products and deployment options to you.

To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---

# 可以正常使用
> show dbs
admin      0.000GB
articledb  0.000GB
config     0.000GB
local      0.000GB
test       0.000GB

        对 articledb 数据库进行登录认证和相关操作,如下:

# 直接进行客户端登录
[root@node1 ~]# /usr/local/mongodb/bin/mongo --host 192.168.229.154 --port 27017 --authenticationDatabase articledb -u bobo -p 123456
MongoDB shell version v4.0.28
connecting to: mongodb://192.168.229.154:27017/?authSource=articledb&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("8fd96137-3a04-4910-8f6f-4c24f8ce6978") }
MongoDB server version: 4.0.28

# 数据库切换
> use articledb
switched to db articledb

# 数据查看
> db.comment.find()
{ "_id" : "1", "articleid" : "100001", "content" : "我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。", "userid" : "1002", "nickname" : "相忘于江湖", "createdatetime" : ISODate("2019-08-05T22:08:15.522Z"), "likenum" : 1000, "state" : "1", "parentid" : "3" }
{ "_id" : "2", "articleid" : "100001", "content" : "我夏天空腹喝凉开水,冬天喝温开水", "userid" : "1005", "nickname" : "伊人憔悴", "createdatetime" : ISODate("2019-08-05T23:58:51.485Z"), "likenum" : 888, "state" : "1", "parentid" : "3" }
{ "_id" : "3", "articleid" : "100001", "content" : "我一直喝凉开水,冬天夏天都喝。", "userid" : "1004", "nickname" : "杰克船长", "createdatetime" : ISODate("2019-08-06T01:05:06.321Z"), "likenum" : NumberLong(667), "state" : "1", "parentid" : "3" }
{ "_id" : "4", "articleid" : "100001", "content" : "专家说不能空腹吃饭,影响健康。", "userid" : "1003", "nickname" : "凯撒", "createdatetime" : ISODate("2019-08-06T08:18:35.288Z"), "likenum" : NumberLong(2001), "state" : "1", "parentid" : "3" }
{ "_id" : "5", "articleid" : "100001", "content" : "研究表明,刚烧开的水千万不能喝,因为烫嘴。", "userid" : "1003", "nickname" : "凯撒", "createdatetime" : ISODate("2019-08-06T11:01:02.521Z"), "likenum" : 3000, "state" : "1" }
{ "_id" : ObjectId("6527b60dcde6f61a6e8eeb59"), "content" : "测试添加的数据", "userid" : "1003", "nickname" : "凯撒大帝", "createdatetime" : ISODate("2023-10-12T09:02:05.315Z"), "likenum" : 0, "replynum" : 0, "state" : "1", "articleid" : "100000", "_class" : "cn.article.po.Comment" }

提示:

        -u :用户名

        -p :密码

        --authenticationDatabase :指定连接到哪个库。当登录是指定用户名密码时,必须指定对应的数据库。

2.4 SpringDataMongoDB 连接认证

        使用用户名和密码连接到 MongoDB 服务器,你必须使用 'username:password@hostname/dbname' 格式,'username' 为用户名,'password' 为密码。

        使用用户 bobo 使用密码 123456 连接到 MongoDB 服务上,如下所示

spring:
  # 数据源配置
  data:
    mongodb:
      # 主机地址
      # host: 192.168.229.154
      # 数据库
      # database: articledb
      # 默认端口是27017
      # port: 27017
      # 也可以使用uri连接
      uri: mongodb://bobo:123456@192.168.229.154:27017/articledb

 三、副本集环境

3.1 前言

        对于之前搭建好的 mongodb 副本集,为了安全,启动安全认证,使用账号密码登录。副本集环境使用之前搭建好的,架构如下:

对副本集执行访问控制需要配置两个方面:

        1)副本集和共享集群的各个节点成员之间使用内部身份验证,可以使用密钥文件或 x.509 证书。密钥文件比较简单,本文使用密钥文件,官方推荐如果是测试环境可以使用密钥文件,但是正式环境,官方推荐 x.509 证书。原理就是,集群中每一个实例彼此连接的时候都检验彼此使用的证书的内容是否相同。只有证书相同的实例彼此才可以访问

        2)使用客户端连接到 mongodb 集群时,开启访问授权。对于集群外部的访问。如通过可视化客户端,或者通过代码连接的时候,需要开启授权。

        在 keyfile 身份验证中,副本集中的每个 mongod 实例都使用 keyfile 的内容作为共享密码,只有具有正确密钥文件的 mongod 或者 mongos 实例可以连接到副本集。密钥文件的内容必须在 61024 个字符之间,并且在 unix/linux 系统中文件所有者必须有对文件至少有的权限。

3.2 关闭已开启的副本集服务

        增加副本集的安全认证和服务鉴权功能,可以在副本集搭建的时候直接添加,也可以在之前搭建好的副本集服务上添加。

        本文使用之前搭建好的副本集服务,因此,先停止之前的集群服务停止服务的方式有两种:快速关闭和标准关闭,下面依次说明:

1):快速关闭方法

        快速,简单,数据可能出错。通过系统的 kill 命令直接杀死进程。杀完要检查一下,避免有的没有杀掉。

# 通过进程编号关闭节点
kill -2 54410

        如果一旦是因为数据损坏,则需要进行如下操作:

# 删除 lock 文件
rm -f /usr/local/mongodb/replica_sets/myrs_27017/data/db/*.lock
rm -f /usr/local/mongodb/replica_sets/myrs_27018/data/db/*.lock
rm -f /usr/local/mongodb/replica_sets/myrs_27019/data/db/*.lock
 
# 修复数据
/usr/local/mongodb/bin/mongod --repair --dbpath=/usr/local/mongodb/replica_sets/myrs_27017/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/usr/local/mongodb/replica_sets/myrs_27018/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/usr/local/mongodb/replica_sets/myrs_27019/data/db

2):标准的关闭方法

        数据不容易出错,但是麻烦。通过 mongo 客户端中的 shutdownServer 命令来关闭服务,如下:

# 客户端登录服务,注意,这里通过 localhost 登录,如果需要远程登录,必须先登录认证才行。
mongo --port 27017

# 告知副本集说本机要下线
rs.stepDown()

# 切换到admin库
use admin
 
# 关闭服务
db.shutdownServer()

3.3 通过主节点添加一个管理员账号

        首先启动三个服务,并通过主节点进行连接,命令如下:

/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27017/mongod.conf

/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27018/mongod.conf

/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27019/mongod.conf


# 登录主节点
/usr/local/mongodb/bin/mongo --host=192.168.229.154 --port=27017

        只需要在主节点上添加用户,副本集会自动同步。开启认证之前,创建超管用户。

myrs:PRIMARY> use admin
switched to db admin

# 创建用户
myrs:PRIMARY> db.createUser({user:"myroot",pwd:"123456",roles:["root"]})
Successfully added user: { "user" : "myroot", "roles" : [ "root" ] }
myrs:PRIMARY>

提示:

        该步骤也可以在开启认证之后,但需要通过 localhost 登录才允许添加用户,用户数据也会自动同步到副本集。后续再创建其他用户,都可以使用该超管用户创建。

3.4 创建副本集认证的 key 文件

        首先生成一个 key 文件到当前文件夹中。

        可以使用任何方法生成密钥文件。例如,以下操作使用 openssl 生成密码文件,然后使用 chmod 来更改文件权限,仅为文件所有者提供读取权限。

# 使用 openssl 生成密码文件
[root@node1 ~]# openssl rand -base64 90 -out ./mongo.keyfile

# 查看当前文件的权限
[root@node1 ~]# ll
total 12
-rw-------. 1 root root 2827 Aug 17 01:34 anaconda-ks.cfg
-rw-r--r--. 1 root root  122 Oct 17 18:44 mongo.keyfile
-rw-------. 1 root root 2107 Aug 17 01:34 original-ks.cfg

# .keyfile 文件只需要可读的属性就可以了,这块更改下文件的权限
[root@node1 ~]# chmod 400 ./mongo.keyfile
[root@node1 ~]# ll
total 12
-rw-------. 1 root root 2827 Aug 17 01:34 anaconda-ks.cfg
-r--------. 1 root root  122 Oct 17 18:44 mongo.keyfile
-rw-------. 1 root root 2107 Aug 17 01:34 original-ks.cfg

提示:

        所有副本集节点都必须要用同一份 keyfile,一般是在一台机器上生成,然后拷贝到其他机器上,且必须有读的权限,否则将来会报错。

        一定要保证密钥文件一致,文件位置随便。但是为了方便查找,建议每台机器都放到一个固定的位置,都放到和配置文件一起的目录中。

        这里将该文件分别拷贝到多个目录中:

[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/replica_sets/myrs_27017
[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/replica_sets/myrs_27018
[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/replica_sets/myrs_27019

3.5 修改配置文件指定 keyfile

        先把服务关闭掉,然后分别编辑几个服务的 mongod.conf 文件,添加相关内容:

vim /usr/local/mongodb/replica_sets/myrs_27017/mongod.conf
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/replica_sets/myrs_27017/mongo.keyfile
  # 开启认证方式运行
  authorization: enabled

        第二台修改: 

vim /usr/local/mongodb/replica_sets/myrs_27018/mongod.conf
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/replica_sets/myrs_27018/mongo.keyfile
  # 开启认证方式运行
  authorization: enabled

        第三台修改: 

vim /usr/local/mongodb/replica_sets/myrs_27019/mongod.conf
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/replica_sets/myrs_27019/mongo.keyfile
  # 开启认证方式运行
  authorization: enabled

3.6 重新启动副本集

        分别启动副本集节点,命令如下:

/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27017/mongod.conf
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27018/mongod.conf
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27019/mongod.conf

        连接主节点客户端,命令如下:

/usr/local/mongodb/bin/mongo --host 192.168.229.154 --port 27017

        测试安全认证: 

# 无法显示数据库信息
myrs:PRIMARY> show dbs
myrs:PRIMARY> 

# 切换数据库
myrs:PRIMARY> use admin
switched to db admin
myrs:PRIMARY> show dbs
myrs:PRIMARY> 

# 进行密码认证
myrs:PRIMARY> db.auth("myroot","123456")
1
myrs:PRIMARY> show dbs
admin      0.000GB
articledb  0.000GB
config     0.000GB
local      0.000GB
test       0.000GB

3.7 主节点添加普通账号

# 用管理员账号登录,切换到 admin 库
myrs:PRIMARY> use admin
switched to db admin

# 管理员账号认证
myrs:PRIMARY> db.auth("myroot","123456")
1

# 切换到要认证的库
myrs:PRIMARY> use articledb
switched to db articledb

# 添加普通用户
myrs:PRIMARY> db.createUser({user: "bobo", pwd: "123456", roles: ["readWrite"]})
Successfully added user: { "user" : "bobo", "roles" : [ "readWrite" ] }

        重新连接,使用普通用户 bobo 重新登录,查看数据。注意:也要使用 rs.status() 命令查看副本集是否健康。

# 登录主节点
[root@node1 ~]# /usr/local/mongodb/bin/mongo --host=192.168.229.154 --port=27017
MongoDB shell version v4.0.28
connecting to: mongodb://192.168.229.154:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("a61da27e-4e18-495c-a93b-ea972d9661dc") }
MongoDB server version: 4.0.28

# 切换库
myrs:PRIMARY> use articledb
switched to db articledb

# 查询数据发现没有权限
myrs:PRIMARY> db.comment.find()
Error: error: {
	"operationTime" : Timestamp(1697594675, 1),
	"ok" : 0,
	"errmsg" : "command find requires authentication",
	"code" : 13,
	"codeName" : "Unauthorized",
	"$clusterTime" : {
		"clusterTime" : Timestamp(1697594675, 1),
		"signature" : {
			"hash" : BinData(0,"eXzvD1CzTPMY96eIGzdxuzHQX2g="),
			"keyId" : NumberLong("7289277628433825794")
		}
	}
}

# 权限认证
myrs:PRIMARY> db.auth("bobo","123456")
1

# 可以查询到数据了
myrs:PRIMARY> db.comment.find()
{ "_id" : ObjectId("6528e8155dabb447bc9211d2"), "articleid" : "100000", "content" : "今天天气真好,阳光明媚", "userid" : "1001", "nickname" : "Rose", "createdatetime" : ISODate("2023-10-13T06:47:49.542Z") }
{ "_id" : "1", "articleid" : "100001", "content" : "我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。", "userid" : "1002", "nickname" : "相忘于江湖", "createdatetime" : ISODate("2019-08-05T22:08:15.522Z"), "likenum" : 1000, "state" : "1" }
{ "_id" : ObjectId("6529073bb141e96f30e1b9a7") }

3.8 SpringDataMongoDB 连接副本集

spring:
  # 数据源配置
  data:
    mongodb:
      # 主机地址
      # host: 192.168.229.154
      # 数据库
      # database: articledb
      # 默认端口是27017
      # port: 27017
      # 也可以使用uri连接
      uri: mongodb://bobo:123456@192.168.229.154:27017,192.168.229.154:27018,192.168.229.154:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs

四、分片集群环境

4.1 关闭已开启的分片集群服务

        分片集群环境下的安全认证和副本集环境下基本上一样。

        但分片集群的服务器环境和架构较为复杂,建议在搭建分片集群的时候,直接加入安全认证和服务器间的鉴权,如果之前有数据,可先将之前的数据备份出来,再还原回去。

        本文使用之前搭建好的集群服务,因此,先停止之前的集群服务。

 1):快速关闭方法

        快速,简单,数据可能出错。通过系统的 kill 命令直接杀死进程。杀完要检查一下,避免有的没有杀掉。

        依次杀死 mongos 路由、配置副本集服务,分片副本集服务,从次节点开始。直到所有成员都离线。副本集杀的时候,建议先杀仲裁者,再杀副本节点,最后是主节点,以避免潜在的回滚。杀完要检查一下,避免有的没有杀掉。

# 通过进程编号关闭节点
kill -2 54410

        如果一旦是因为数据损坏,则需要进行如下操作:

# 删除 lock 文件
rm -f /usr/local/mongodb/sharded_cluster/myshardrs01_27018/data/db/*.lock
rm -f /usr/local/mongodb/sharded_cluster/myshardrs01_27118/data/db/*.lock
rm -f /usr/local/mongodb/sharded_cluster/myshardrs01_27218/data/db/*.lock
rm -f /usr/local/mongodb/sharded_cluster/myshardrs02_27318/data/db/*.lock
rm -f /usr/local/mongodb/sharded_cluster/myshardrs02_27418/data/db/*.lock
rm -f /usr/local/mongodb/sharded_cluster/myshardrs02_27518/data/db/*.lock
rm -f /usr/local/mongodb/sharded_cluster/myconfigrs_27019/data/db/*.lock
rm -f /usr/local/mongodb/sharded_cluster/myconfigrs_27119/data/db/*.lock
rm -f /usr/local/mongodb/sharded_cluster/myconfigrs_27219/data/db/*.lock

 
# 依次修复数据
/usr/local/mongodb/bin/mongod --repair --dbpath=/usr/local/mongodb/sharded_cluster/myshardrs01_27018/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/usr/local/mongodb/sharded_cluster/myshardrs01_27118/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/usr/local/mongodb/sharded_cluster/myshardrs01_27218/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/usr/local/mongodb/sharded_cluster/myshardrs02_27318/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/usr/local/mongodb/sharded_cluster/myshardrs02_27418/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/usr/local/mongodb/sharded_cluster/myshardrs02_27518/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/usr/local/mongodb/sharded_cluster/myconfigrs_27019/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/usr/local/mongodb/sharded_cluster/myconfigrs_27119/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/usr/local/mongodb/sharded_cluster/myconfigrs_27219/data/db

2):标准的关闭方法

        数据不容易出错,但是麻烦。通过 mongo 客户端中的 shutdownServer 命令来关闭服务。

        关闭分片服务器副本集中的服务,建议依次关闭仲裁节点、副本节点、主节点。主要的操作步骤参考如下:

# 客户端登录服务,注意,这里通过 localhost 登录,如果需要远程登录,必须先登录认证才行。
mongo --port 27019

# 告知副本集说本机要下线
rs.stepDown()

# 切换到admin库
use admin
 
# 关闭服务
db.shutdownServer()
# 客户端登录服务,注意,这里通过 localhost 登录,如果需要远程登录,必须先登录认证才行。
mongo --port 27018

# 告知副本集说本机要下线
rs.stepDown()

# 切换到admin库
use admin
 
# 关闭服务
db.shutdownServer()
# 客户端登录服务,注意,这里通过 localhost 登录,如果需要远程登录,必须先登录认证才行。
mongo --port 27017

# 告知副本集说本机要下线
rs.stepDown()

# 切换到admin库
use admin
 
# 关闭服务
db.shutdownServer()

 4.2 创建副本集认证的 key 文件

        首先生成一个 key 文件到当前文件夹中。

        可以使用任何方法生成密钥文件。例如,以下操作使用 openssl 生成密码文件,然后使用 chmod 来更改文件权限,仅为文件所有者提供读取权限。

# 使用 openssl 生成密码文件
[root@node1 ~]# openssl rand -base64 90 -out ./mongo.keyfile

# 查看当前文件的权限
[root@node1 ~]# ll
total 12
-rw-------. 1 root root 2827 Aug 17 01:34 anaconda-ks.cfg
-rw-r--r--. 1 root root  122 Oct 17 18:44 mongo.keyfile
-rw-------. 1 root root 2107 Aug 17 01:34 original-ks.cfg

# .keyfile 文件只需要可读的属性就可以了,这块更改下文件的权限
[root@node1 ~]# chmod 400 ./mongo.keyfile
[root@node1 ~]# ll
total 12
-rw-------. 1 root root 2827 Aug 17 01:34 anaconda-ks.cfg
-r--------. 1 root root  122 Oct 17 18:44 mongo.keyfile
-rw-------. 1 root root 2107 Aug 17 01:34 original-ks.cfg

提示:

        所有副本集节点都必须要用同一份 keyfile,一般是在一台机器上生成,然后拷贝到其他机器上,且必须有读的权限,否则将来会报错。

        一定要保证密钥文件一致,文件位置随便。但是为了方便查找,建议每台机器都放到一个固定的位置,都放到和配置文件一起的目录中。

        这里将该文件分别拷贝到多个目录中:

[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/sharded_cluster/myshardrs01_27018
[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/sharded_cluster/myshardrs01_27118
[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/sharded_cluster/myshardrs01_27218
[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/sharded_cluster/myshardrs02_27318
[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/sharded_cluster/myshardrs02_27418
[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/sharded_cluster/myshardrs02_27518
[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/sharded_cluster/myconfigrs_27019
[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/sharded_cluster/myconfigrs_27119
[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/sharded_cluster/myconfigrs_27219
[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/sharded_cluster/mymongos_27017
[root@node1 ~]# cp mongo.keyfile /usr/local/mongodb/sharded_cluster/mymongos_27117

4.3 修改配置文件指定 keyfile

        分别编辑几个服务的 mongod.conf 文件,添加相关内容

vim /usr/local/mongodb/sharded_cluster/myshardrs01_27018/mongod.conf

# 添加内容
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/sharded_cluster/myshardrs01_27018/mongo.keyfile
  # 开启认证方式运行
  authorization: enabled
vim /usr/local/mongodb/sharded_cluster/myshardrs01_27118/mongod.conf

# 添加内容
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/sharded_cluster/myshardrs01_27118/mongo.keyfile
  # 开启认证方式运行
  authorization: enabled
vim /usr/local/mongodb/sharded_cluster/myshardrs01_27218/mongod.conf

# 添加内容
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/sharded_cluster/myshardrs01_27218/mongo.keyfile
  # 开启认证方式运行
  authorization: enabled
vim /usr/local/mongodb/sharded_cluster/myshardrs02_27318/mongod.conf

# 添加内容
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/sharded_cluster/myshardrs02_27318/mongo.keyfile
  # 开启认证方式运行
  authorization: enabled
vim /usr/local/mongodb/sharded_cluster/myshardrs02_27418/mongod.conf

# 添加内容
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/sharded_cluster/myshardrs02_27418/mongo.keyfile
  # 开启认证方式运行
  authorization: enabled
vim /usr/local/mongodb/sharded_cluster/myshardrs02_27518/mongod.conf

# 添加内容
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/sharded_cluster/myshardrs02_27518/mongo.keyfile
  # 开启认证方式运行
  authorization: enabled
vim /usr/local/mongodb/sharded_cluster/myconfigrs_27019/mongod.conf

# 添加内容
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/sharded_cluster/myconfigrs_27019/mongo.keyfile
  # 开启认证方式运行
  authorization: enabled
vim /usr/local/mongodb/sharded_cluster/myconfigrs_27119/mongod.conf

# 添加内容
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/sharded_cluster/myconfigrs_27119/mongo.keyfile
  # 开启认证方式运行
  authorization: enabled
vim /usr/local/mongodb/sharded_cluster/myconfigrs_27219/mongod.conf

# 添加内容
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/sharded_cluster/myconfigrs_27219/mongo.keyfile
  # 开启认证方式运行
  authorization: enabled
vim /usr/local/mongodb/sharded_cluster/mymongos_27017/mongos.conf

# 添加内容
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/sharded_cluster/mymongos_27017/mongo.keyfile
vim /usr/local/mongodb/sharded_cluster/mymongos_27117/mongos.conf

# 添加内容
security:
  # KeyFile鉴权文件
  keyFile: /usr/local/mongodb/sharded_cluster/mymongos_27117/mongo.keyfile

        mongos mongod 少了 authorization:enabled 的配置。原因是,副本集加分片的安全认证需要配置两方面的,副本集各个节点之间使用内部身份验证,用于内部各个 mongo 实例的通信,只有相同 keyfile 才能相互访问。所以都要开启 keyFile

        然而对于所有的 mongod,才是真正的保存数据的分片。mongos 只做路由,不保存数据。所以所有的 mongod 开启访问数据的授权 authorization:enabled。这样用户只有账号密码正确才能访问到数据。

4.4 重新启动节点

/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/sharded_cluster/myconfigrs_27019/mongod.conf
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/sharded_cluster/myconfigrs_27119/mongod.conf
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/sharded_cluster/myconfigrs_27219/mongod.conf

/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/sharded_cluster/myshardrs01_27018/mongod.conf
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/sharded_cluster/myshardrs01_27118/mongod.conf
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/sharded_cluster/myshardrs01_27218/mongod.conf

/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/sharded_cluster/myshardrs02_27318/mongod.conf
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/sharded_cluster/myshardrs02_27418/mongod.conf
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/sharded_cluster/myshardrs02_27518/mongod.conf

/usr/local/mongodb/bin/mongos -f /usr/local/mongodb/sharded_cluster/mymongos_27017/mongos.conf
/usr/local/mongodb/bin/mongos -f /usr/local/mongodb/sharded_cluster/mymongos_27117/mongos.conf

注意:

        这里有个非常特别的情况,就是启动顺序。先启动配置节点,再启动分片节点,最后启动路由节点。如果先启动分片节点,就会卡住。

4.5 创建账号认证

        客户端 mongo,通过 localhost 登录任意一个 mongos 路由

# 登录路由节点
[root@node1 ~]# /usr/local/mongodb/bin/mongo --port 27017
MongoDB shell version v4.0.28
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("709b93d0-7c24-4305-b8cb-573b70af10eb") }
MongoDB server version: 4.0.28
# 切换库
mongos> use admin
switched to db admin
# 创建管理员用户
mongos> db.createUser({user:"myroot",pwd:"123456",roles:["root"]})
Successfully added user: { "user" : "myroot", "roles" : [ "root" ] }

        创建一个普通权限账号

mongos> use admin
switched to db admin
mongos> db.auth("myroot","123456")
1
mongos> use articledb
switched to db articledb
mongos> db.createUser({user: "bobo", pwd: "123456", roles: [{ role: "readWrite",db: "articledb" }]})
Successfully added user: {
	"user" : "bobo",
	"roles" : [
		{
			"role" : "readWrite",
			"db" : "articledb"
		}
	]
}
mongos> db.auth("bobo","123456")
1

提示:

        通过 mongos 添加的账号信息,只会保存到配置节点的服务中,具体的数据节点不保存账号信息,因此,分片中的账号信息不涉及到同步问题。 

         mongo 客户端登录 mongos 路由,用管理员帐号登录可查看分片情况:

mongos> use admin
switched to db admin
mongos> sh.status()

# 无法正常访问
2023-10-17T23:09:10.337-0700 E QUERY    [js] Error: error: {
	"ok" : 0,
	"errmsg" : "command find requires authentication",
	"code" : 13,
	"codeName" : "Unauthorized",
	"operationTime" : Timestamp(1697609349, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1697609349, 1),
		"signature" : {
			"hash" : BinData(0,"3y1pnzMYM9gAO7JoWO82yob1boA="),
			"keyId" : NumberLong("7290456107330306068")
		}
	}
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DBCommandCursor@src/mongo/shell/query.js:708:1
DBQuery.prototype._exec@src/mongo/shell/query.js:113:28
DBQuery.prototype.hasNext@src/mongo/shell/query.js:288:5
DBCollection.prototype.findOne@src/mongo/shell/collection.js:260:10
printShardingStatus@src/mongo/shell/utils_sh.js:532:19
sh.status@src/mongo/shell/utils_sh.js:94:5
@(shell):1:1

# 用户登录
mongos> db.auth("myroot","123456")
1

# 可以正常访问
mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
  	"_id" : 1,
  	"minCompatibleVersion" : 5,
  	"currentVersion" : 6,
  	"clusterId" : ObjectId("652ce7344991027264953cbe")
  }
  shards:
        {  "_id" : "myshardrs01",  "host" : "myshardrs01/192.168.229.154:27018,192.168.229.154:27118",  "state" : 1 }
        {  "_id" : "myshardrs02",  "host" : "myshardrs02/192.168.229.154:27318,192.168.229.154:27418",  "state" : 1 }
  active mongoses:
        "4.0.28" : 2
  autosplit:
        Currently enabled: yes
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  5
        Last reported error:  Could not find host matching read preference { mode: "primary" } for set myshardrs02
        Time of Reported error:  Tue Oct 17 2023 21:08:31 GMT-0700 (PDT)
        Migration Results for the last 24 hours: 
                No recent migrations
  databases:
        {  "_id" : "articledb",  "primary" : "myshardrs02",  "partitioned" : true,  "version" : {  "uuid" : UUID("14943571-dd3e-4b0b-84c4-7d3a05d5e0a0"),  "lastMod" : 1 } }
                articledb.author
                        shard key: { "age" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                myshardrs01	8
                                myshardrs02	9
                        { "age" : { "$minKey" : 1 } } -->> { "age" : 0 } on : myshardrs01 Timestamp(2, 0) 
                        { "age" : 0 } -->> { "age" : 8 } on : myshardrs01 Timestamp(5, 2) 
                        { "age" : 8 } -->> { "age" : 17 } on : myshardrs01 Timestamp(5, 3) 
                        { "age" : 17 } -->> { "age" : 26 } on : myshardrs01 Timestamp(5, 4) 
                        { "age" : 26 } -->> { "age" : 34 } on : myshardrs01 Timestamp(4, 8) 
                        { "age" : 34 } -->> { "age" : 43 } on : myshardrs01 Timestamp(4, 9) 
                        { "age" : 43 } -->> { "age" : 52 } on : myshardrs01 Timestamp(4, 10) 
                        { "age" : 52 } -->> { "age" : 60 } on : myshardrs01 Timestamp(5, 0) 
                        { "age" : 60 } -->> { "age" : 70 } on : myshardrs02 Timestamp(5, 1) 
                        { "age" : 70 } -->> { "age" : 79 } on : myshardrs02 Timestamp(4, 7) 
                        { "age" : 79 } -->> { "age" : 83 } on : myshardrs02 Timestamp(5, 5) 
                        { "age" : 83 } -->> { "age" : 87 } on : myshardrs02 Timestamp(5, 6) 
                        { "age" : 87 } -->> { "age" : 92 } on : myshardrs02 Timestamp(5, 7) 
                        { "age" : 92 } -->> { "age" : 100 } on : myshardrs02 Timestamp(4, 2) 
                        { "age" : 100 } -->> { "age" : 109 } on : myshardrs02 Timestamp(4, 3) 
                        { "age" : 109 } -->> { "age" : 119 } on : myshardrs02 Timestamp(4, 4) 
                        { "age" : 119 } -->> { "age" : { "$maxKey" : 1 } } on : myshardrs02 Timestamp(3, 4) 
                articledb.comment
                        shard key: { "nickname" : "hashed" }
                        unique: false
                        balancing: true
                        chunks:
                                myshardrs01	2
                                myshardrs02	2
                        { "nickname" : { "$minKey" : 1 } } -->> { "nickname" : NumberLong("-4611686018427387902") } on : myshardrs01 Timestamp(1, 0) 
                        { "nickname" : NumberLong("-4611686018427387902") } -->> { "nickname" : NumberLong(0) } on : myshardrs01 Timestamp(1, 1) 
                        { "nickname" : NumberLong(0) } -->> { "nickname" : NumberLong("4611686018427387902") } on : myshardrs02 Timestamp(1, 2) 
                        { "nickname" : NumberLong("4611686018427387902") } -->> { "nickname" : { "$maxKey" : 1 } } on : myshardrs02 Timestamp(1, 3) 
        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }
                config.system.sessions
                        shard key: { "_id" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                myshardrs01	512
                                myshardrs02	512
                        too many chunks to print, use verbose if you want to force print

        退出连接,重新连接服务,使用普通权限帐号访问数据。

# 登录
[root@node1 ~]# /usr/local/mongodb/bin/mongo --port 27017
MongoDB shell version v4.0.28
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("b80f0d28-1bde-4432-9930-528035301165") }
MongoDB server version: 4.0.28

# 库切换
mongos> use articledb
switched to db articledb

# 无法正常访问
mongos> show collections
Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus

# 安全认证之后可以正常访问
mongos> db.auth("bobo","123456")
1
mongos> show collections
author
comment

4.6 SpringDataMongoDB 连接认证

spring:
  # 数据源配置
  data:
    mongodb:
      # 主机地址
      # host: 192.168.229.154
      # 数据库
      # database: articledb
      # 默认端口是27017
      # port: 27017
      # 也可以使用uri连接
      uri: mongodb://bobo:123456@192.168.229.154:27017,192.168.229.154:27117/articledb
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐的小三菊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值