Neo4j系列导航:
neo4j安装及简单实践
cypher语法基础
cypher插入语法
cypher插入语法
cypher查询语法
cypher通用语法
cypher函数语法
neo4j索引及调优
neo4j java Driver等更多
1.简介
Kerberos是一种网络身份验证协议,它允许网络节点在网络上证明其身份。它通过使用密钥分发中心(KDC)来确保客户端标识是正确的。除了安全性之外,Kerberos还支持单点登录。这允许在登录到计算机后授予用户对数据库的访问权限,从而为用户提供了简单性。
- Neo4j支持使用Kerberos:4.x、5.x版本支持
2.部署
官方的Neo4j Kerberos Add-on可用于通过Kerberos身份验证扩展Neo4j。该附加组件提供身份验证,并应与其他提供程序(如LDAP)一起用于授权。
- Neo4j Kerberos Add-on v4.0.0与Neo4j的4.x和5.x所有版本兼容
Kerberos Add-on的部署步骤:
将kerberos-add-on.jar文件放在Neo4j安装的plugins/目录中。编辑neo4j.conf以启用Kerberos附加组件作为身份验证提供者。
-
为Kerberos配置Neo4j:
Configure neo4j.conf
#For authentication with kerberos-add-on dbms.security.authentication_providers=plugin-Neo4j-Kerberos dbms.security.authorization_providers=ldap #For authorization with LDAP dbms.security.ldap.host=ad.windomain.local dbms.security.ldap.authorization.use_system_account=true dbms.security.ldap.authorization.system_username=CN=neo4jservice,OU=IT-Services,DC=windomain,DC=local dbms.security.ldap.authorization.system_password=PASSWORD dbms.security.ldap.authorization.user_search_base=CN=Users,DC=windomain,DC=local dbms.security.ldap.authorization.user_search_filter=(&(objectClass=*)(SamAccountName={0})) dbms.security.ldap.authorization.group_membership_attributes=memberOf dbms.security.ldap.authorization.group_to_role_mapping= \ "CN=Neo4j Read Only,CN=Users,DC=windomain,DC=local" = reader; \ "CN=Neo4j Read-Write,CN=Users,DC=windomain,DC=local" = publisher; \ "CN=Neo4j Schema Manager,CN=Users,DC=windomain,DC=local" = architect; \ "CN=Neo4j Administrator,CN=Users,DC=windomain,DC=local" = admin; \ "CN=Neo4j Procedures,CN=Users,DC=windomain,DC=local" = allowed_role
-
生成Kerberos keytab文件:
为KDC中的Neo4j服务器创建一个服务用户。确保为Neo4j服务用户生成一个keytab,并将其放在conf目录中。在本例中,我们将其命名为neo4j.ktab。keytab将被Neo4j使用。 -
配置Kerberos Add-on:
如果您已经通过Heimdal或MIT工具套件使用Kerberos,那么您有一个krb5.conf文件,其中包含有关如何访问KDC的信息。如果您没有这样的文件,或者不希望使用它,请在conf目录中创建一个新的krb5.conf文件。配置krb5.conf:
在本例中,我们使用的是WINDOMAIN领域。LOCAL和KDC和管理服务器的IP地址192.168.38.2。将它们分别替换为KDC和管理服务器的实际领域和实际IP或域名。[libdefaults] default_realm = WINDOMAIN.LOCAL default_tgs_enctypes = rc4-hmac rc4-hmac-exp aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha1-96 des3-hmac-sha1 default_tkt_enctypes = rc4-hmac rc4-hmac-exp aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha1-96 des3-hmac-sha1 permitted_enctypes = rc4-hmac rc4-hmac-exp aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha1-96 des3-hmac-sha1 [realms] WINDOMAIN.LOCAL = { kdc = 192.168.38.2 admin_server = 192.168.38.2 } [domain_realm] .windomain.local = WINDOMAIN.LOCAL windomain.local = WINDOMAIN.LOCAL
Java本身不支持某些加密算法。当使用更高级的加密算法(例如ASE-256)时,确保运行Neo4j的Java启用了Java Cryptography Extension扩展。
现在在conf目录中创建第二个名为kerberos.conf的文件。keytab设置引用上面创建的keytab文件。该服务。主体设置是该keytab中的主体,krb5.conf设置引用krb5.conf文件(已经从现有Kerberos安装中存在,或者在上面步骤中创建)。同样,根据您的设置将这些值替换为正确的值。
配置kerberos.conf:
realm=WINDOMAIN.LOCAL keytab=conf/neo4j.ktab service.principal=neo4j/neo4j.windomain.local@WINDOMAIN.LOCAL krb5.conf=conf/krb5.conf
3.使用
要使用Kerberos进行身份验证的客户机应用程序代码必须针对KDC进行身份验证,并获取Neo4j服务的服务票证(在我们的示例中:Neo4j /neo4j.windomain.local@WINDOMAIN.LOCAL)。服务ticket必须直接或封装在SPNEGO(1.3.6.1.5.5.2)中使用Kerberos v5(1.2.840.113554.1.2.2)机制。
服务ticket应该以以下属性的认证令牌形式提供给Neo4j驱动程序:
- Principal: empty
- Credentials: the Base64-encoded service ticket
- Realm: add-on-Neo4j-Kerberos
Kerberos Add-on目前不能与Neo4j浏览器一起工作。它
只适用于使用Neo4j驱动程序的应用程序
。
实例一:Java驱动
使用1.3 Java驱动程序的示例实现
public void connect()
{
byte[] serviceTicket = get(serviceDomainName);
String scheme = "ticket";
String realm = "add-on-Neo4j-Kerberos";
String encodedServiceTicket = Base64.getEncoder().encodeToString( serviceTicket );
AuthToken token = AuthTokens.custom( encodedServiceTicket );
try ( Driver driver = GraphDatabase.driver( "bolt://" + serviceDomainName, token ) )
{
// do interesting things
}
}
public byte[] get(String serviceDomainName) throws LoginException, GSSException
{
Map<String,String> options = Collections.singletonMap( "useTicketCache", "true" );
Krb5Configuration loginContextConfiguration = new Krb5Configuration( options );
LoginContext loginContext = new LoginContext(
"KerberosClient",
null, // this is the subject
null, // no need for this
loginContextConfiguration
);
loginContext.login();
return getServiceTicket( loginContext.getSubject(), "neo4j@" + serviceDomainName );
}
public static final Oid SPNEGO_OID = getOid( "1.3.6.1.5.5.2" );
public byte[] getServiceTicket(Subject subject, String servicePrincipalName) throws GSSException
{
GSSManager manager = GSSManager.getInstance();
GSSName serverName = manager.createName( servicePrincipalName, GSSName.NT_HOSTBASED_SERVICE );
final GSSContext context = manager.createContext(
serverName, SPNEGO_OID, null, GSSContext.DEFAULT_LIFETIME );
// The GSS context initiation has to be performed as a privileged action.
return Subject.doAs( subject, new PrivilegedAction<byte[]>()
{
public byte[] run()
{
try
{
// This is a one pass context initialisation.
context.requestMutualAuth( false );
context.requestCredDeleg( false );
return context.initSecContext( new byte[0], 0, 0 );
}
catch ( GSSException e )
{
e.printStackTrace();
return null;
}
}
} );
}
private class Krb5Configuration extends Configuration
{
private final AppConfigurationEntry[] configList;
public Krb5Configuration( Map<String,String> options )
{
this.configList = new AppConfigurationEntry[1];
configList[0] =
new AppConfigurationEntry(
"com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
options
);
}
@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name)
{
return configList;
}
}
实例一:c#驱动
使用c#和1.3 . net驱动程序实现的示例
var token = AuthTokens.kerberos(getTicket("neo4j"));
using (var driver = GraphDatabase.Driver("bolt://neo4j.windomain.local:7687", token))
{
try
{
using (var session = driver.Session())
{
var result = session.Run("MATCH () RETURN count(*) AS count");
foreach (var record in result)
{
Console.WriteLine($"Nodecount: {record["count"].As<string>()}");
}
}
}
catch (Exception e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
private static String getTicket(string serviceName)
{
AppDomain.CurrentDomain.SetPrincipalPolicy(System.Security.Principal.PrincipalPolicy.WindowsPrincipal);
var domain = Domain.GetCurrentDomain().ToString();
using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
{
string spn = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, serviceName).UserPrincipalName;
Console.WriteLine("Service Principale name: " + spn);
KerberosSecurityTokenProvider tokenProvider = new KerberosSecurityTokenProvider(spn);
KerberosRequestorSecurityToken securityToken = tokenProvider.GetToken(TimeSpan.FromMinutes(1)) as KerberosRequestorSecurityToken;
var token = securityToken.GetRequest();
String ticket = Convert.ToBase64String(token);
return ticket;
}
}