标签:
RMI Server(服务端)主要包括以下功能:远程用户权限验证管理、远程服务接口实现类、Neo4j实体映射转换等。项目目录结构如下图所示:
用户权限验证机制分为三个层级。
第一级,远程主机IP地址验证。检查是否允许远程主机IP地址访问RMI服务。
第二级,远程用户信息验证。检查用户名称和密码是否正确,用户是否启用等。
第三级,远程服务及接口方法验证。检查用户是否有权访问某个RMI服务以及服务下的指定接口方法。
远程用户配置信息在文件remote.users.config.xml中,内容格式如下表所示:
<?xml version="1.0"?> <remote-users> <remote-user user-id="1" login-name="admin" password="admin" user-name="管理员用户" enabled="true"></remote-user> <remote-user user-id="2" login-name="test" password="test" user-name="测试用户" enabled="true"></remote-user> </remote-users>
远程主机配置信息在文件remote.hosts.config.xml中,内容格式如下表所示:
<?xml version="1.0"?> <hosts> <allow-hosts> <host>*</host> </allow-hosts> <forbid-hosts> <host></host> </forbid-hosts> </hosts>
用户权限配置信息在文件remote.users.permission.xml中,内容格式如下表所示:
<?xml version="1.0"?> <remote-users> <remote-user login-name="admin,test"> <remote-service name="neo4j-graph-manage-service"> <allow-methods> <method>*</method> </allow-methods> <forbid-methods> <method></method> </forbid-methods> </remote-service> <remote-service name="neo4j-graph-node-service"> <allow-methods> <method>*</method> </allow-methods> <forbid-methods> <method></method> </forbid-methods> </remote-service> <remote-service name="neo4j-graph-index-service"> <allow-methods> <method>*</method> </allow-methods> <forbid-methods> <method></method> </forbid-methods> </remote-service> <remote-service name="neo4j-graph-path-service"> <allow-methods> <method>*</method> </allow-methods> <forbid-methods> <method></method> </forbid-methods> </remote-service> <remote-service name="neo4j-graph-cypher-service"> <allow-methods> <method>*</method> </allow-methods> <forbid-methods> <method></method> </forbid-methods> </remote-service> </remote-user> </remote-users>
绝大部分的非业务类工作都是在远程服务基础接口实现类BaseRemoteServiceImpl中完成了,譬如,获取图数据库服务对象实例、用户权限验证、日志记录、Neo4j实体映射转换等。如下表所示:
package com.hnepri.neo4j.rmi.service; import java.rmi.RemoteException; import java.rmi.server.RemoteServer; import java.rmi.server.ServerNotActiveException; import java.rmi.server.UnicastRemoteObject; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.Iterator; import java.util.List; import org.apache.commons.lang.StringUtils; import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.Label; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Path; import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.RelationshipType; import org.neo4j.graphdb.Transaction; import com.hnepri.common.util.DateTimeUtil; import com.hnepri.neo4j.client.rmi.bean.GDirection; import com.hnepri.neo4j.client.rmi.bean.GNode; import com.hnepri.neo4j.client.rmi.bean.GPage; import com.hnepri.neo4j.client.rmi.bean.GPath; import com.hnepri.neo4j.client.rmi.bean.GRelationship; import com.hnepri.neo4j.client.rmi.service.IBaseRemoteService; import com.hnepri.neo4j.client.rmi.util.RemoteClientFactory; import com.hnepri.neo4j.client.rmi.util.RemoteLoginStatusUtil; import com.hnepri.neo4j.common.model.GraphPageModel; import com.hnepri.neo4j.common.util.GraphTemplate; import com.hnepri.neo4j.rmi.bean.RemoteUser; import com.hnepri.neo4j.rmi.util.RemoteHostUtil; import com.hnepri.neo4j.rmi.util.RemoteServerFactory; import com.hnepri.neo4j.rmi.util.RemoteUserPermissionUtil; import com.hnepri.neo4j.rmi.util.RemoteUserUtil; /** * Description: 远程服务基类实现类<br> * Copyright: Copyright (c) 2015<br> * Company: 河南电力科学研究院智能电网所<br> * @author shangbingbing 2015-09-01编写 * @version 1.0 */ @SuppressWarnings("deprecation") public class BaseRemoteServiceImpl extends UnicastRemoteObject implements IBaseRemoteService { private static final long serialVersionUID = 7292764643219275924L; private String loginName = ""; private String password = ""; private String serviceName = ""; private String clientAddress = ""; private boolean loginStatus = false; private String loginStatusMessage = ""; private String graphName; private String graphPath; /** * 获取图数据库操作实例GraphTemplate * @return */ public GraphTemplate getTemplate() { if(StringUtils.isNotBlank(this.getGraphName())) { return GraphTemplate.getInstanceByName(this.getGraphName()); } else { return GraphTemplate.getInstance(this.getGraphPath()); } } public BaseRemoteServiceImpl() throws RemoteException { super(); } /** * 获取登录用户名称 * @return */ protected String getLoginName() { return loginName; } /** * 获取登录用户密码 * @return */ protected String getPassword() { return password; } /** * 获取远程服务名称(主要用于记录日志) * @return */ protected String getServiceName() { return serviceName; } /** * 设置远程服务名称(主要用于记录日志) * @param serviceName */ protected void setServiceName(String serviceName) { this.serviceName = serviceName; } protected String getClientAddress() { try { this.clientAddress = RemoteServer.getClientHost(); } catch (ServerNotActiveException e) { e.printStackTrace(); } return clientAddress; } /** * 获取用户登录状态。 * @return */ protected boolean getLoginStatus() { return loginStatus; } /** * 获取用户登录状态信息。 * @return */ protected String getLoginStatusMessage() { return loginStatusMessage; } /** * 获取当前数据库名称。 * @return */ public String getGraphName() { return graphName; } /** * 获取当前数据库路径。 * @return */ public String getGraphPath() { return graphPath; } /** * 检查远程调用方法的权限 * @param methodName */ protected void checkRemoteMethodPermission(String methodName) throws RemoteException { boolean hasPermission = RemoteUserPermissionUtil.isCanAccessServiceMethod(this.getLoginName(), this.getServiceName(), methodName); if(hasPermission) { String log = String.format("%s\t来自【%s】的用户【%s】调用%s中的接口方法【%s】一次!", DateTimeUtil.getFormatDateTime(new Date()), this.getClientAddress(), this.getLoginName(), this.getServiceName(), methodName); RemoteServerFactory.addLog(log); } else { String log = String.format("警告:来自【%s】的用户【%s】无权调用%s中的接口方法【%s】!", this.getClientAddress(), this.getLoginName(), this.getServiceName(), methodName); RemoteServerFactory.addLog(log); throw new RemoteException(log); } } @Override public String remoteTest() throws RemoteException { return RemoteClientFactory.REMOTE_CALL_STATUS_SUCCESS; } @Override public int login(String loginName, String password) throws RemoteException { this.loginName = loginName; this.password = password; RemoteServerFactory.addLog(String.format("%s\t来自【%s】的用户【%s】正在验证访问【%s】服务!", DateTimeUtil.getFormatDateTime(new Date()), this.getClientAddress(), this.getLoginName(), this.getServiceName())); int loginStatusValue = RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS; if(RemoteHostUtil.isAllowHostAccess(this.getClientAddress())) { if(StringUtils.isBlank(loginName) || StringUtils.isBlank(password)) { loginStatusValue = RemoteLoginStatusUtil.LOGIN_STATUS_USER_PASSWORD_EMPTY; } else { if(RemoteUserUtil.getRemoteUserList().containsKey(loginName)) { if(RemoteUserUtil.getRemoteUserList().get(loginName).isEnabled()) { RemoteUser user = RemoteUserUtil.getRemoteUserList().get(loginName); if(user.getPassword().equals(password)) { if(RemoteUserPermissionUtil.isCanAccessService(loginName, this.getServiceName())) { loginStatusValue = RemoteLoginStatusUtil.LOGIN_STATUS_SUCCESS; if(RemoteUserUtil.getOnlineRemoteHostList().containsKey(this.getClientAddress())) { RemoteUserUtil.getOnlineRemoteHostList().remove(this.getClientAddress()); } RemoteUserUtil.getOnlineRemoteHostList().put(this.getClientAddress(), DateTimeUtil.getFormatDateTime(new Date())); if(RemoteUserUtil.getOnlineRemoteUserList().containsKey(this.getLoginName())) { RemoteUserUtil.getOnlineRemoteUserList().remove(this.getLoginName()); } RemoteUserUtil.getOnlineRemoteUserList().put(this.getLoginName(), DateTimeUtil.getFormatDateTime(new Date())); } else { loginStatusValue = RemoteLoginStatusUtil.LOGIN_STATUS_USER_PERMISSION_ERROR; } } else { loginStatusValue = RemoteLoginStatusUtil.LOGIN_STATUS_PASSWORD_ERROR; } } else { loginStatusValue = RemoteLoginStatusUtil.LOGIN_STATUS_USER_ERROR; } } else { loginStatusValue = RemoteLoginStatusUtil.LOGIN_STATUS_USER_ERROR; } } } else { loginStatusValue = RemoteLoginStatusUtil.LOGIN_STATUS_IP_PERMISSION_ERROR; } this.loginStatusMessage = RemoteClientFactory.parseLoginStatusValue(loginStatusValue); if(loginStatusValue == 0) { this.loginStatus = true; RemoteServerFactory.addLog(String.format("%s\t来自【%s】的用户【%s】通过【%s】服务的访问验证!", DateTimeUtil.getFormatDateTime(new Date()), this.getClientAddress(), this.getLoginName(), this.getServiceName())); } else { this.loginStatus = false; RemoteServerFactory.addLog(String.format("%s\t来自【%s】的用户【%s】未通过【%s】服务的访问验证。\r\n%s", DateTimeUtil.getFormatDateTime(new Date()), this.getClientAddress(), this.getLoginName(), this.getServiceName(), this.getLoginStatusMessage())); } return loginStatusValue; } @Override public void initGraphName(String graphName) throws RemoteException { this.graphName = graphName; } @Override public void initGraphPath(String graphPath) throws RemoteException { this.graphPath = graphPath; } }
Neo4j实体映射转换,即将Neo4j原生的接口类对象映射转换为我们在RMI Client中自定义的可序列化的远程服务实体类。主要转换方法如下所示。
/** * 将Node转换为GNode对象。<br> * <b>【备注:未进行事务处理】</b> * @param node * @return */ protected GNode convertNodeToGNode(Node node) { if(node == null) { return null; } GNode gnode = new GNode(); gnode.setId(node.getId()); gnode.setDegree(node.getDegree()); Iterator<Label> itLabel = node.getLabels().iterator(); while(itLabel.hasNext()) { Label label = itLabel.next(); gnode.getLabelNameList().add(label.name()); } for(String name : node.getAllProperties().keySet()) { Object value = node.getProperty(name); gnode.getPropertyList().put(name, value); } Iterator<Relationship> itRelationship = node.getRelationships().iterator(); while(itRelationship.hasNext()) { Relationship rel = itRelationship.next(); String relType = rel.getType().name(); gnode.getRelationshipList().add(rel.getId()); if(gnode.getRelationshipTypeList().containsKey(relType)) { gnode.getRelationshipTypeList().get(relType).add(rel.getId()); } else { ArrayList<Long> list = new ArrayList<Long>(); list.add(rel.getId()); gnode.getRelationshipTypeList().put(relType, list); } } Iterator<Relationship> itRelationshipIncoming = node.getRelationships(Direction.INCOMING).iterator(); ArrayList<Long> incomingList = new ArrayList<Long>(); while(itRelationshipIncoming.hasNext()) { Relationship rel = itRelationshipIncoming.next(); incomingList.add(rel.getId()); } gnode.getRelationshipDirectionList().put(Direction.INCOMING.name(), incomingList); Iterator<Relationship> itRelationshipOutgoing = node.getRelationships(Direction.OUTGOING).iterator(); ArrayList<Long> outgoingList = new ArrayList<Long>(); while(itRelationshipOutgoing.hasNext()) { Relationship rel = itRelationshipOutgoing.next(); outgoingList.add(rel.getId()); } gnode.getRelationshipDirectionList().put(Direction.OUTGOING.name(), outgoingList); return gnode; } /** * 将Node对象转换为GNode对象。<br> * <b>【备注:已进行事务处理】</b> * @param nodes * @return */ public List<GNode> parseNodes(List<Node> nodes) { List<GNode> gNodeList = new ArrayList<GNode>(); if(nodes == null || nodes.size() == 0) return gNodeList; if(this.getTemplate() == null) return gNodeList; Transaction tx = this.getTemplate().createTransaction(); try { for(Node node : nodes) { GNode gnode = this.convertNodeToGNode(node); if(gnode == null) continue; gNodeList.add(gnode); } } catch (Exception ex) { ex.printStackTrace(); tx.failure(); } finally { tx.finish(); } return gNodeList; } /** * 将Node对象转换为GNode对象。<br> * <b>【备注:已进行事务处理】</b> * @param node * @return */ public GNode parseNode(Node node) { List<Node> nodes = Arrays.asList(node); List<GNode> gNodeList = this.parseNodes(nodes); if(gNodeList == null || gNodeList.size() == 0) { return null; } else { return gNodeList.get(0); } } /** * 根据编码解析节点对象,将其转为GNode对象。<br> * <b>【备注:已进行事务处理】</b> * @param nodeIDs * @return */ public List<GNode> parseNodesByID(List<Long> nodeIDs) { List<GNode> gNodeList = new ArrayList<GNode>(); if(nodeIDs == null || nodeIDs.size() == 0) return gNodeList; if(this.getTemplate() == null) return gNodeList; Transaction tx = this.getTemplate().createTransaction(); try { for(long nodeID : nodeIDs) { Node node = this.getTemplate().getGraphDBService().getNodeById(nodeID); GNode gnode = this.convertNodeToGNode(node); if(gnode == null) continue; gNodeList.add(gnode); } } catch (Exception ex) { ex.printStackTrace(); tx.failure(); } finally { tx.finish(); } return gNodeList; } /** * 根据编码解析节点对象,将其转为GNode对象。<br> * <b>【备注:已进行事务处理】</b> * @param nodeID * @return */ public GNode parseNodeByID(long nodeID) { List<Long> nodeIDs = Arrays.asList(nodeID); List<GNode> gNodeList = this.parseNodesByID(nodeIDs); if(gNodeList == null || gNodeList.size() == 0) { return null; } else { return gNodeList.get(0); } } /** * 将Relationship转换为GRelationship对象。<br> * <b>【备注:未进行事务处理】</b> * @param relationship * @return */ protected GRelationship convertRelToGRel(Relationship relationship) { if(relationship == null) { return null; } GRelationship grelationship = new GRelationship(); grelationship.setId(relationship.getId()); grelationship.setStartNodeID(relationship.getStartNode().getId()); grelationship.setEndNodeID(relationship.getEndNode().getId()); grelationship.setRelationshipType(relationship.getType().name()); for(String name : relationship.getAllProperties().keySet()) { Object value = relationship.getProperty(name); grelationship.getPropertyList().put(name, value); } return grelationship; } /** * 将Relationship对象转换为GRelationship对象。<br> * <b>【备注:已进行事务处理】</b> * @param relationships * @return */ public List<GRelationship> parseRelationships(List<Relationship> relationships) { List<GRelationship> gRelationshipList = new ArrayList<GRelationship>(); if(relationships == null || relationships.size() == 0) return gRelationshipList; if(this.getTemplate() == null) return gRelationshipList; Transaction tx = this.getTemplate().createTransaction(); try { for(Relationship relationship : relationships) { GRelationship grelationship = this.convertRelToGRel(relationship); if(grelationship == null) continue; gRelationshipList.add(grelationship); } } catch (Exception ex) { ex.printStackTrace(); tx.failure(); } finally { tx.finish(); } return gRelationshipList; } /** * 将Relationship对象转换为GRelationship对象。<br> * <b>【备注:已进行事务处理】</b> * @param relationship * @return */ public GRelationship parseRelationship(Relationship relationship) { List<Relationship> relationships = Arrays.asList(relationship); List<GRelationship> gRelationshipList = this.parseRelationships(relationships); if(gRelationshipList == null || gRelationshipList.size() == 0) { return null; } else { return gRelationshipList.get(0); } } /** * 根据编码解析关系对象,将其转为GRelationship对象。<br> * <b>【备注:已进行事务处理】</b> * @param relationshipIDs * @return */ public List<GRelationship> parseRelationshipsByID(List<Long> relationshipIDs) { List<GRelationship> gRelationshipList = new ArrayList<GRelationship>(); if(relationshipIDs == null || relationshipIDs.size() == 0) return gRelationshipList; if(this.getTemplate() == null) return gRelationshipList; Transaction tx = this.getTemplate().createTransaction(); try { for(long relationshipID : relationshipIDs) { Relationship relationship = this.getTemplate().getGraphDBService().getRelationshipById(relationshipID); GRelationship grelationship = this.convertRelToGRel(relationship); if(grelationship == null) continue; gRelationshipList.add(grelationship); } } catch (Exception ex) { ex.printStackTrace(); tx.failure(); } finally { tx.finish(); } return gRelationshipList; } /** * 根据编码解析关系对象,将其转为GRelationship对象。<br> * <b>【备注:已进行事务处理】</b> * @param relationshipID * @return */ public GRelationship parseRelationshipByID(long relationshipID) { List<Long> relationshipIDs = Arrays.asList(relationshipID); List<GRelationship> gRelationshipList = this.parseRelationshipsByID(relationshipIDs); if(gRelationshipList == null || gRelationshipList.size() == 0) { return null; } else { return gRelationshipList.get(0); } } /** * 将Path对象转换为GPath对象。<br> * <b>【备注:未进行事务处理】</b> * @param paths * @return */ protected List<GPath> convertPathToGPath(List<Path> paths) { List<GPath> gPathList = new ArrayList<GPath>(); if(paths == null || paths.size() == 0) return gPathList; for(Path path : paths) { GPath gpath = new GPath(); Iterator<Node> itNode = path.nodes().iterator(); while(itNode.hasNext()) { Node node = itNode.next(); GNode gnode = this.convertNodeToGNode(node); if(gnode == null) continue; gpath.getNodes().add(gnode); } Iterator<Relationship> itRelationship = path.relationships().iterator(); while(itRelationship.hasNext()) { Relationship relationship = itRelationship.next(); GRelationship grelationship = this.convertRelToGRel(relationship); if(grelationship == null) continue; gpath.getRelationships().add(grelationship); } gPathList.add(gpath); } return gPathList; } /** * 将Path对象转换为GPath对象。<br> * <b>【备注:未进行事务处理】</b> * @param path * @return */ protected GPath convertPathToGPath(Path path) { List<Path> paths = Arrays.asList(path); List<GPath> gPathList = this.convertPathToGPath(paths); if(gPathList == null || gPathList.size() == 0) { return null; } else { return gPathList.get(0); } } /** * 将GPage对象转换为GraphPageModel对象。 * @param gpage * @return */ public GraphPageModel parseGPageToGraphPageModel(GPage gpage) { GraphPageModel pageModel = null; if(gpage == null) { pageModel = new GraphPageModel(20); } else { pageModel = new GraphPageModel(gpage.getPageSize()); pageModel.setPageIndex(gpage.getPageIndex()); pageModel.setTotalCount(gpage.getTotalCount()); } return pageModel; } /** * 将GraphPageModel对象转换为GPage对象。 * @param pageModel * @return */ public GPage parseGraphPageModelToGPage(GraphPageModel pageModel) { GPage gpage = null; if(pageModel == null) { gpage = new GPage(20); } else { gpage = new GPage(pageModel.getPageSize()); gpage.setPageIndex(pageModel.getPageIndex()); gpage.setTotalCount(pageModel.getTotalCount()); List<GNode> nodeList = this.parseNodes(pageModel.getNodeList()); for(GNode node : nodeList) { gpage.getNodeList().add(node); } List<GRelationship> relationshipList = this.parseRelationships(pageModel.getRelationshipList()); for(GRelationship relationship : relationshipList) { gpage.getRelationshipList().add(relationship); } } return gpage; } /** * 将GDirection对象转换为Direction对象。 * @param gdirection * @return */ public Direction parseGDirection(GDirection gDirection) { if(gDirection == null) { return null; } if(StringUtils.isBlank(gDirection.getName())) { return null; } return Direction.valueOf(gDirection.getName()); } /** * 将关系类型名称解析为关系类型枚举对象。 * @param relationshipType * @return */ public RelationshipType parseRelationshipType(String relationshipType) { if(StringUtils.isBlank(relationshipType)) { return null; } return this.getTemplate().getRelTypeUtil().get(relationshipType); }
RMI Server Form,即RMI服务窗口管理器,是通过窗口方式来管理RMI服务,包括启动RMI服务,停止RMI服务,监控RMI日志信息,监控远程登录用户信息,初始化相关配置等操作。此功能集成在“图数据库管理系统Server端”,功能界面如下图所示:
【完】
作者:商兵兵
单位:河南省电力科学研究院智能电网所
QQ:52190634
Neo4j图数据库管理系统开发笔记之三:构建安全的RMI Service(Server)
标签:
原文地址:http://www.cnblogs.com/shangbingbing/p/5028791.html