• IDEA操作MongoDB及安全认证


    一、Java整合MongoDB

    1.java连接MongoDB

    • 在new project那里创建一个普通的maven项目mongodbexample。

    • 引入java整合MongoDB的依赖

      <!-- 引入java整合MongoDB的依赖 -->
      <dependency>
          <groupId>org.mongodb</groupId>
          <artifactId>mongo-java-driver</artifactId>
          <version>3.12.11</version>
      </dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 在java根目录的com.zzx的包下,创建类MongoDBExample,添加如下代码

      public class MongoDBExample {
          public static void main(String[] args) {
              //获取mongodb连接地址
              String connectionString = System.getProperty("mongodb.uri");
              try {
                  MongoClient mongoClient = MongoClients.create(connectionString);
                  ArrayList<Document> databases = mongoClient.listDatabases().into(new ArrayList<>());
                  databases.forEach(db-> System.out.println(db.toJson()));
              }catch (Exception e)
              {
                  e.printStackTrace();
              }
      
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15

      即连接到mongodb并输出所有数据库

    • 点击Alt+Shift+F10,选择Edit Configuration,然后选择modify options->选择Add VM options,在框内输入该参数:-Dmongodb.uri="mongodb://192.168.126.16:27017/?maxPoolSize=2&w=majority",最后点击run即可。

    • 在java根目录的com.zzx的包下,创建类MongoDBExample2,添加如下代码:

      public class MongoDBExample2 {
          public static void main(String[] args) {
              Properties properties = new Properties();
              try {
                  //使用classLoader加载properties文件生成对应的输入流
                  InputStream resourceAsStream = MongoDBExample2.class.getClassLoader().getResourceAsStream("config.properties");
                  //使用properties对象加载输入流
                  properties.load(resourceAsStream);
                  //获取属性对应的value值
                  String connectionString = properties.getProperty("mongodb.uri");
                  System.out.println(connectionString);
                  //获取MongoClient对象
                  MongoClient mongoClient = MongoClients.create(connectionString);
                  ArrayList<Document> databases = mongoClient.listDatabases().into(new ArrayList<>());
                  databases.forEach(db-> System.out.println(db.toJson()));
              } catch (IOException e) {
                  throw new RuntimeException(e);
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
    • 在resources目录下,创建配置文件config.properties,添加如下配置:mongodb.uri=mongodb://192.168.126.16:27017/?maxPoolSize=2&w=majority

    2.java操作MongoDB

    • 新建一个类,MongoDBCRUD,将获取MongoClient对象的部分封装到方法中

      public class MongoDBCRUD {
          public static void main(String[] args) {
              try {
                  MongoClient mongoClient = getMongoClient("config.properties");
              } catch (IOException e) {
                  throw new RuntimeException(e);
              }finally {
              mongoClient.close();
          	}
          }
      
          /**
           * 获取MongoClient对象
           * @param propertyFileName
           * @return
           * @throws IOException
           */
          private static MongoClient getMongoClient(String propertyFileName) throws IOException {
         		Properties properties = new Properties();
          	//使用classLoader加载properties文件生成对应的输入流
              InputStream resourceAsStream = MongoDBCRUD.class.getClassLoader().getResourceAsStream(propertyFileName);
              //使用properties对象加载输入流
              properties.load(resourceAsStream);
              //获取属性对应的value值
              String connectionString = properties.getProperty("mongodb.uri");
              //获取MongoClient对象
              MongoClient mongoClient = MongoClients.create(connectionString);
              return mongoClient;
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
    • 创建集合,即在获取MongoClient对象后面添加如下两行

      //获取database数据库对象mydb
      MongoDatabase mydb = mongoClient.getDatabase("mydb");
      //创建集合
      mydb.createCollection("exampleCollection");
      
      • 1
      • 2
      • 3
      • 4
    • 添加文档,代码如下:

      //获取集合对象
      MongoCollection<Document> collection = mydb.getCollection("exampleCollection");
      //创建文档对象
      Document document = Document.parse("{name: 'zhangsan',city: 'beijing',birthday: new ISODate('2000-04-02'),expectSalary: 18000}");
      //插入文档
      collection.insertOne(document);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 查询文档

       //创建文档对象
       Document document = Document.parse("{name: 'zhangtao',city: 'beijing',birthday: new ISODate('2000-04-02'),expectSalary: 13000}");
       Document document2 = Document.parse("{name: 'lisi',city: 'beijing',birthday: new ISODate('2000-04-02'),expectSalary: 12000}");
       Document document3 = Document.parse("{name: 'wangwu',city: 'beijing',birthday: new ISODate('2000-04-02'),expectSalary: 16000}");
      
       //插入文档
       collection.insertOne(document);
       collection.insertOne(document2);
       collection.insertOne(document3);
      
       //按照expectSalary倒排
       Document expectSalary = new Document();
       expectSalary.append("expectSalary", -1);
       FindIterable<Document> findIterable = collection.find().sort(expectSalary);
       for (Document doc:findIterable) {
            System.out.println(doc);
        }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
    • 查询指定条件的文档

      //按指定的属性值查询
      FindIterable<Document> documents = collection.find(new Document("expectSalary", new Document("$eq", 16000)));
      for (Document doc:documents) {
           System.out.println(doc);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 查询过滤文档

       //过滤查询 gt大于,gte大于等于
      FindIterable<Document> filtersexpectSalary = collection.find(Filters.gte("expectSalary", 13000)).sort(expectSalary);
      for (Document doc:filtersexpectSalary) {
      System.out.println(doc);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5

    二、SpringBoot整合MongoDB

    1.搭建MongoDB的web项目

    • 创建一个SpringBoot项目mongodb-springboot,在pom文件中添加如下配置:

      <properties>
          <java.version>11</java.version>
          <spring-boot-version>2.7.3</spring-boot-version>
      </properties>
      <dependencyManagement>
          <dependencies>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-dependencies</artifactId>
                  <version>${spring-boot-version}</version>
                  <type>pom</type>
                  <scope>import</scope>
              </dependency>
          </dependencies>
      </dependencyManagement>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
    • 删除父项目的src模块,并把pom文件的dependencies标签的文件全部删除,也就是springboot和springboottest的启动依赖。

    • 通过new Module,在mongodb-springboot项目中创建web子项目mongodb-test,并在子项目的pom文件中引入如下依赖

      	<!-- 引入springboot的web依赖 -->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <!-- 引入springboot整合mongodb的依赖 -->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-data-mongodb</artifactId>
          </dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

      同时父类的pom文件会自动更新为pom类型,并出现modules标签,内部有mongodb-test子模块。

    • 在mongodb-test子模块中的java根目录下,创建包com.zzx,并在包下创建springboot启动类,代码如下:

      @SpringBootApplication
      public class MongodbTestApplication {
          public static void main(String[] args) {
              SpringApplication.run(MongodbTestApplication.class, args);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 在mongodb-test子模块中的resources目录下创建配置文件application.properties

      spring.data.mongodb.host=192.168.126.16
      spring.data.mongodb.port=27017
      spring.data.mongodb.database=mydb
      
      • 1
      • 2
      • 3

    2.访问MongoDB的业务代码实现

    • 在父工程的pom文件的dependencyManagement中引入lombok依赖进行版本管理

      <dependency>
      	<groupId>org.projectlombok</groupId>
      	<artifactId>lombok</artifactId>
       	<version>${lombok-version}</version>
      </dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 在子项目的pom文件中引入lombok依赖

      <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
      </dependency>
      
      • 1
      • 2
      • 3
      • 4
    • 在com.zzx包下,创建包entity,在该包下创建实体类Orders,代码如下

      import lombok.*;
      
      import java.io.Serializable;
      import java.util.Date;
      @Data
      @EqualsAndHashCode
      @NoArgsConstructor
      @ToString
      public class Orders implements Serializable {
          private String _id;
          private String name;
          private String size;
          private Integer price;
          private Integer quantity;
          private Date date;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

    2.1 注入MongoTemplate使用MongoDB

    • 在com.zzx包下,创建包dao,在该包下创建dao层接口OrderDao,代码如下:

      public interface OrderDao{
          //根据订单名称查询订单集合
          List<Orders> findOrdersByName(String name);
      }
      
      • 1
      • 2
      • 3
      • 4
    • 在com.zzx.dao包下,创建包impl,在该包下创建实现类OrderDaoImpl,代码如下:

      @Repository
      public class OrderDaoImpl implements OrderDao {
      
          @Autowired
          private MongoTemplate mongoTemplate;
      
          /**
           * 按订单名称查询
           * @param name
           * @return
           */
          @Override
          public List<Orders> findOrdersByName(String name) {
              Query query = new Query();
              query.addCriteria(Criteria.where("name").is(name));
              return mongoTemplate.find(query,Orders.class);
          }
      }	
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
    • 在com.zzx包下,创建包service,在该包下创建service层接口OrderService,代码如下:

      public interface OrderService {
          // 按订单名称查询
          List<Orders> findOrdersByName(String name);
      }
      
      • 1
      • 2
      • 3
      • 4
    • 在com.zzx.service包下,创建包impl,在该包下创建实现类OrderServiceImpl,代码如下:

      @Service
      public class OrderServiceImpl implements OrderService {
          @Autowired
          private OrderDao orderDao;
          @Override
          public List<Orders> findOrdersByName(String name) {
              return orderDao.findOrdersByName(name);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • 在com.zzx包下,创建包controller,在该包下创建controller层OrderController,代码如下:

      @RestController
      @RequestMapping("orders")
      public class OrderController {
          @Autowired
          private OrderService orderService;
      
          @GetMapping("/getOrders")
          public List<Orders> findOrdersByName(String name)
          {
              return orderService.findOrdersByName(name);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

    2.2 继承MongoRepository使用MongoDB

    • 在com.zzx包下,创建包repository,在该包下创建接口OrdersRepository,代码如下:

      public interface OrdersRepository extends MongoRepository<Orders,String> {
          /**
           * 按订单名称查询订单
           * @param name
           * @return
           */
          List<Orders> findOrdersByName(String name);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      MongoRepository相当于MybatisPlus。

    • 在OrderService接口中,加入如下代码: List findOrdersByName_2(String name);

    • 在OrderServiceImpl实现类中,加入如下代码:

      @Autowired
      private OrdersRepository ordersRepository;
      @Override
      public List<Orders> findOrdersByName_2(String name) {
          return ordersRepository.findOrdersByName(name);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 在OrderController类中,添加如下代码:

      @GetMapping("/getOrders2")
      public List<Orders> findOrdersByName_2(String name)
      {
          return orderService.findOrdersByName_2(name);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5

    三、MongoDB的安全认证及内置角色

    1.MongoDB的安全认证

    • MongoDB默认是没有账号的,可以直接连接,无须身份验证。实际项目中肯定要权限验证,否则后果不堪设想。

    • 进入到容器中,备份数据:mongodump -h 127.0.0.1:27017 -d mydb -o /usr/local

    • 进入到容器中,备份全部数据:mongodump
      即所有数据库备份文件创建在当前目录的/dump目录下

    • 将mongo的dump目录,复制到/usr/local目录:docker cp mongo5:/dump /usr/local/

    • 关闭mongo5容器:docker stop mongo5

    • 以auth方式启动MongoDB:docker run -itd --name mongo6 -p 27017:27017 mongo:5.0.11-focal --auth

    • 将备份复制到mongo6:docker cp /usr/local/dump/ mongo6:/dump

    • 进入到mongo6容器:docker exec -it mongo6 bash

    • 进入到mongo命令行客户端,切换到admin数据库。创建MongoDB登录用户以及分配权限的方式

    db.createUser({
    	user: "root",
    	pwd: "123456",
    	roles:[{role: "root",db:"admin"}]
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5

    参数:
    roles:为用户分配的角色,不同的角色拥有不同的权限,参数是数组,可以同时设置多个
    role:角色,MongoDB已经约定好的角色,不同角色对应不同的权限。
    db:数据库名称,MongoDB默认自带的有admin、local、config、test等,即为数据库实例设置用户

    • 验证用户后可以更改密码、添加角色、恢复数据等操作:db.auth("root","123456")
      返回1,即验证成功
    • 删除用户:db.dropUser("用户名")
    • 修改密码:db.changeUserPassword("root","root")
    • 添加角色:db.grantRolesToUser("用户名",[{role: "角色名",db: "数据库名"}])
    • 恢复数据:mongorestore -h localhost -u root -p 123456 --db mydb /dump/mydb --authenticationDatabase admin
    • NoSQLBooster可视化连接:
      在这里插入图片描述

    2.MongoDB内置角色(role)

    1. read:允许用户读取指定数据库
    2. readWrite:允许用户读写指定数据库
    3. dbAdmin:可以读取任何数据库并对库进行清理、修改、压缩,获取统计信息、执行检查等操作
    4. userAdmin:可以在指定数据库里创建、删除和管理用户
    5. readAnyDatabase:可以读取任何数据库中的数据,除了数据库config和local之外
    6. readWriteAnyDatabase:可以读写任何数据库中的数据。除了数据库config和local之外
    7. userAdminAnyDatabase:可以在任何数据库总创建、删除和管理用户,除了数据库config和local之外
    8. dbAdminAnyDatabase:可以读取任何数据库并对库进行清理、修改、压缩,获取统计信息、执行检查等操作,除了数据库config和local之外
    9. root:超级账号,超级权限
    10. backup:备份数据权限
    11. restore:从备份中恢复数据的权限

    3.MongoDB内置角色的访问控制

    • 创建管理员(即root)
      MongoDB服务端在开启安全检查之前,至少需要有一个管理员账号,admin数据库中的用户都被视为管理员,如果admin库没有任何用户的话,即使在其他数据库创建了用户,启用身份验证,默认的连接方式依然会有超级权限,即仍然可以不验证账号密码,照样能进行CRUD,此时的安全认证失效。
      在mongo命令行客户端中,首先use admin,然后创建管理员
    db.createUser({
    	user: "root",
    	pwd: "123456",
    	roles:[{role: "root",db:"admin"}]
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 创建普通用户
      • 创建有读写权限的用户zhangsan,指定数据库mydb
        db.createUser({
        	user: "zhangsan",
        	pwd: "123456",
        	roles:[{role: "readWrite",db:"mydb"}]
        })
        
        • 1
        • 2
        • 3
        • 4
        • 5
      • 创建有读权限的用户lisi,指定数据库mydb
        db.createUser({
        	user: "lisi",
        	pwd: "123456",
        	roles:[{role: "read",db:"mydb"}]
        })
        
        • 1
        • 2
        • 3
        • 4
        • 5
    • 验证用户zhangsan,此时需要先退出客户端重新进入,否则会出现验证2个用户名的错误:db.auth("zhangsan","123456")
      • 插入数据:db.c1.insert({name:"testdb1"})
      • 查询集合c1所有文档:db.c1.find()
        即只有mydb的读写权限
    • 先use mydb,验证用户lisi:db.auth("lisi","123456")
      • 查询集合c1所有文档:db.c1.find()
        即只有mydb的读权限

    总结:

    1. java连接MongoDB,将MongoDB服务器的Ip地址及端口号再加上一些参数单独写在properties文件中或者通过Edit Ciguration配置,在程序中读出来,通过MongoClients创建连接,再通过MangoClient获取数据库。
    2. springboot连接MongoDB,在配置文件中指定ip地址及端口号和数据库名;调用MongoTemplate函数进行查询操作即可。而不用手动去读取配置文件,再获取数据库及集合。而是交给springboot来做,甚至都不用指定集合,springboot应该是首先通过实体类名去找对应的集合。
    3. SpringBoot整合MongoDB可以使用两种方式,MongoTemplate以及MongoRepository。
      MongoTemplate方式需要Dao层的实现类去实现;而MongoRepository方式则不需要定义实现类,但是需要Dao层去继承MongoRepository并指定其实体类及查询条件类型。
    4. 在创建超级权限用户时,需要use admin。
      进行权限验证之前,要先use database(对应的数据库),才可以进行权限验证。
      更改密码、添加角色、恢复数据等操作需要权限验证。
      权限验证后,可以进行show dbs,查看自己有权限的数据库。
  • 相关阅读:
    分布式事务(Seata)——Seata分布式事务XA模式、AT模式、TCC模式的介绍和对比 & 结合案例分析AT模式和XA模式【源码】
    iMazing2023iOS系统设备数据传输与备份工具使用教程
    【2024】LitCTF
    麒麟操作系统安装人大金仓数据库
    分享一些常用的小程序免费源码
    Backtrader官方中文文档
    36 | SRE的工作职责
    【LeetCode力扣】86. 分隔链表
    重点用能单位能耗系统在湖南三立集团的应用
    Docker快速入门
  • 原文地址:https://blog.csdn.net/weixin_49076273/article/details/126541430