目录
前言
传统数据库难以处理复杂多跳的关系运算。需要一种支持海量、复杂、且结构灵活的关系运算数据库,图数据库应运而生,Neo4j是一个高性能的,NOSQL图形数据库。
1、使用Neo4j引擎包调用Api
1.1 引入Neo4j引擎Jar包
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>4.4.5</version>
</dependency>
1.2 调用Neo4j引擎Api
public static void main(String[] args) {
Driver driver = GraphDatabase.driver("bolt://192.168.104.118:7687", AuthTokens.basic("neo4j", "admin123"));
Session session = driver.session();
session.run("CREATE (n:Domain {ip: $ip,port: $port})",
parameters( "ip", "192.168.100.1", "port", "80" ));
session.run("CREATE (n:Domain {ip: $ip,port: $port})",
parameters( "ip", "192.168.100.2", "port", "80" ));
session.run("CREATE (n:Domain {ip: $ip,port: $port})",
parameters( "ip", "192.168.100.3", "port", "80" ));
session.run("CREATE (n:Domain {ip: $ip,port: $port})",
parameters( "ip", "192.168.100.1", "port", "90" ));
session.run("CREATE (n:Domain {ip: $ip,port: $port})",
parameters( "ip", "192.168.100.2", "port", "90" ));
session.run("CREATE (n:Domain {ip: $ip,port: $port})",
parameters( "ip", "192.168.100.3", "port", "90" ));
Result result = session.run( "MATCH (n:Domain) WHERE n.ip = $ip " +
"RETURN n.ip as ip, n.port as port",
parameters( "ip", "192.168.100.1"));
while (result.hasNext()) {
Record record = result.next();
System.out.println(record.get("ip") +":"+ record.get("port"));
}
session.close();
driver.close();
}
代码输出:
"192.168.100.1":"80"
"192.168.100.1":"90"
查看Neo4j可视化窗口节点显示
2、使用Spring-Data-Neo4j调用Api
2.1 集成Spring-Data-Neo4j
2.1.1 Maven引入spring-boot-starter-data-neo4j的jar包
<!-- version需要跟springboot使用同version -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
<version>${spring-boot.version}</version>
</dependency>
2.1.2 Spring配置文件添加Neo4j连接配置
spring:
neo4j:
authentication:
password: admin123
username: neo4j
uri: bolt://192.168.104.118:7687
2.2 创建Neo4jEntity
2.2.1 VulEntity
package com.kg.neo4jEntity;
import lombok.Data;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Relationship;
import java.util.List;
@Node("Vul")
@Data
public class VulEntity {
@Id
private String code;
private String name;
private String cveCode;
private String level;
private String dataSourceCode;
private String type;
private String source;
private String cvss;
private String introduction;
private String translation;
private String affectedEntity;
private String referenceUrl;
private String patch;
private String label;
private String vendor;
private String poc;
@Relationship(type = "影响资产", direction = Relationship.Direction.OUTGOING)
private List<AssetsEntity> assetsEntityList;
}
2.2.2 AssetsEntity
package com.kg.neo4jEntity;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Relationship;
import java.util.List;
@Node("Assets")
@Data
@NoArgsConstructor
public class AssetsEntity {
@Id
private String id;
private String name;
private String local;
private String source;
private String type;
private String version;
@Relationship(type = "存在漏洞", direction = Relationship.Direction.OUTGOING)
private List<VulEntity> vulEntityList;
}
2.2 创建Spring-data-Neo4j的DAO接口
2.2.1 VulRepository
package com.kg.repository;
import com.kg.neo4jEntity.VulEntity;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface VulRepository extends Neo4jRepository<VulEntity,String> {
}
2.2.2 AssetsRepository
package com.kg.repository;
import com.kg.neo4jEntity.AssetsEntity;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface AssetsRepository extends Neo4jRepository<AssetsEntity,String> {
}
2.3 测试
2.3.1 添加vul节点
@Test
public void saveVulNode() {
// vul1节点
VulEntity vulEntity1 = new VulEntity();
vulEntity1.setCode(UUID.randomUUID().toString());
vulEntity1.setCveCode("CVE-2022-00002");
vulEntity1.setCvss("9.1");
vulEntity1.setIntroduction("添加vul1节点");
vulEntity1.setLabel("测试节点1");
vulEntity1 = vulRepository.save(vulEntity1);
if(vulEntity1 != null){
System.out.println("vulEntity1---save---success");
}else{
System.out.println("vulEntity1---save---fail");
}
// vul2节点
VulEntity vulEntity2 = new VulEntity();
vulEntity2.setCode(UUID.randomUUID().toString());
vulEntity2.setCveCode("CVE-2022-00001");
vulEntity2.setCvss("9.1");
vulEntity2.setIntroduction("添加vul2节点");
vulEntity2.setLabel("测试节点2");
vulEntity2 = vulRepository.save(vulEntity2);
if(vulEntity2 != null){
System.out.println("vulEntity2---save---success");
}else{
System.out.println("vulEntity2---save---fail");
}
}
代码输出:vulEntity1—save—success vulEntity2—save—success
查看Neo4j可视化窗口节点显示
2.3.2 添加assets节点
@Test
public void saveAssetsNode() {
AssetsEntity assetsEntity1 = new AssetsEntity();
assetsEntity1.setId(UUID.randomUUID().toString());
assetsEntity1.setName("测试资产1");
assetsEntity1.setSource("CNNVD");
assetsEntity1 = assetsRepository.save(assetsEntity1);
if(assetsEntity1 != null){
System.out.println("assetsEntity1---save---success");
}else{
System.out.println("assetsEntity1---save---fail");
}
AssetsEntity assetsEntity2 = new AssetsEntity();
assetsEntity2.setId(UUID.randomUUID().toString());
assetsEntity2.setName("测试资产2");
assetsEntity2.setSource("CNNVD");
assetsEntity2 = assetsRepository.save(assetsEntity2);
if(assetsEntity2 != null){
System.out.println("assetsEntity2---save---success");
}else{
System.out.println("assetsEntity2---save---fail");
}
}
代码输出:assetsEntity1—save—success assetsEntity2—save—success
查看Neo4j可视化窗口节点显示
2.3.3 添加vul节点与assets节点关系
@Test
public void saveAssetsVul(){
AssetsEntity assetsEntity = new AssetsEntity();
assetsEntity.setName("测试资产");
List<AssetsEntity> assetsEntityList = assetsRepository.findAll(Example.of(assetsEntity, ExampleMatcher.matching().withMatcher(
"name", ExampleMatcher.GenericPropertyMatchers.contains()
)));
VulEntity vulEntity = new VulEntity();
vulEntity.setLabel("测试节点");
List<VulEntity> vulEntityList = vulRepository.findAll(Example.of(vulEntity, ExampleMatcher.matching().withMatcher(
"label", ExampleMatcher.GenericPropertyMatchers.contains()
)));
List<VulEntity> finalVulEntityList = vulEntityList;
assetsEntityList.forEach(assets -> {
assets.setVulEntityList(finalVulEntityList);
});
assetsEntityList = assetsRepository.saveAll(assetsEntityList);
if(assetsEntityList !=null && assetsEntityList.size() > 0){
System.out.println("assetsEntityList---saveAll---success");
}else{
System.out.println("assetsEntityList---saveAll---fail");
}
List<AssetsEntity> finalAssetsEntityList = assetsEntityList;
vulEntityList.forEach(vul -> {
vul.setAssetsEntityList(finalAssetsEntityList);
});
vulEntityList = vulRepository.saveAll(vulEntityList);
if(vulEntityList !=null && vulEntityList.size() > 0){
System.out.println("vulEntityList---saveAll---success");
}else{
System.out.println("vulEntityList---saveAll---fail");
}
}
代码输出:assetsEntityList—saveAll—success,vulEntityList—saveAll—success
查看Neo4j可视化窗口节点显示
2.3.4 spring-data-neo4j自带方法查询节点
@Test
public void findNeo4j(){
//查询全部
List<VulEntity> vulEntityList = vulRepository.findAll();
System.out.println("vulEntityList:"+vulEntityList);
//根据id查询
Optional<VulEntity> byId = vulRepository.findById("bc5db88c-2f9d-4573-b1d5-5153ba89cbe8");
System.out.println("byId:"+byId);
//根据条件查询 需要Example对象,Example对象包含查询条件与对应条件的类型,以下查询条件字段为label,值为"测试节点"
// ExampleMatcher.GenericPropertyMatchers.contains()代表此字段只需要包含就查出,相当于like
VulEntity vulEntity = new VulEntity();
vulEntity.setLabel("测试节点");
List<VulEntity> vulEntityListByLabel = vulRepository.findAll(Example.of(vulEntity, ExampleMatcher.matching().withMatcher(
"label", ExampleMatcher.GenericPropertyMatchers.contains()
)));
System.out.println("vulEntityListByLabel:"+vulEntityListByLabel);
}
代码输出:
vulEntityList:[VulEntity(code=bc5db88c-2f9d-4573-b1d5-5153ba89cbe8, name=null, cveCode=CVE-2022-00002, level=null, dataSourceCode=null, type=null, source=null, cvss=9.1, introduction=添加vul1节点, translation=null, affectedEntity=null, referenceUrl=null, patch=null, label=测试节点1, vendor=null, poc=null), VulEntity(code=2db9025e-c649-42fe-a7d0-e2d21d103878, name=null, cveCode=CVE-2022-00001, level=null, dataSourceCode=null, type=null, source=null, cvss=9.1, introduction=添加vul2节点, translation=null, affectedEntity=null, referenceUrl=null, patch=null, label=测试节点2, vendor=null, poc=null)]
byId:Optional[VulEntity(code=bc5db88c-2f9d-4573-b1d5-5153ba89cbe8, name=null, cveCode=CVE-2022-00002, level=null, dataSourceCode=null, type=null, source=null, cvss=9.1, introduction=添加vul1节点, translation=null, affectedEntity=null, referenceUrl=null, patch=null, label=测试节点1, vendor=null, poc=null)]
vulEntityListByLabel:[VulEntity(code=bc5db88c-2f9d-4573-b1d5-5153ba89cbe8, name=null, cveCode=CVE-2022-00002, level=null, dataSourceCode=null, type=null, source=null, cvss=9.1, introduction=添加vul1节点, translation=null, affectedEntity=null, referenceUrl=null, patch=null, label=测试节点1, vendor=null, poc=null), VulEntity(code=2db9025e-c649-42fe-a7d0-e2d21d103878, name=null, cveCode=CVE-2022-00001, level=null, dataSourceCode=null, type=null, source=null, cvss=9.1, introduction=添加vul2节点, translation=null, affectedEntity=null, referenceUrl=null, patch=null, label=测试节点2, vendor=null, poc=null)]
2.3.5 使用cypher语法查询
2.3.5.1 自定义cql
package com.kg.repository;
import com.kg.neo4jEntity.VulEntity;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface VulRepository extends Neo4jRepository<VulEntity,String> {
@Query("MATCH (n:Vul) where n.label contains $label RETURN n")
List<VulEntity> getVulEntityByLabel(@Param("label") String label);
}
2.3.5.2 测试
@Test
public void queryNeo4j(){
List<VulEntity> vulEntityListByLabel = vulRepository.getVulEntityByLabel("测试节点");
System.out.println("vulEntityListByLabel:"+vulEntityListByLabel);
}
代码输出:
vulEntityListByLabel:[VulEntity(code=bc5db88c-2f9d-4573-b1d5-5153ba89cbe8, name=null, cveCode=CVE-2022-00002, level=null, dataSourceCode=null, type=null, source=null, cvss=9.1, introduction=添加vul1节点, translation=null, affectedEntity=null, referenceUrl=null, patch=null, label=测试节点1, vendor=null, poc=null), VulEntity(code=2db9025e-c649-42fe-a7d0-e2d21d103878, name=null, cveCode=CVE-2022-00001, level=null, dataSourceCode=null, type=null, source=null, cvss=9.1, introduction=添加vul2节点, translation=null, affectedEntity=null, referenceUrl=null, patch=null, label=测试节点2, vendor=null, poc=null)]