OrientDB - 如何 - 使用 ODocument 记录级别安全性
OrientDB - How To - Record Level Security with ODocument
我正在尝试 Record Level Security 使用文档数据库 (Java) API for OrientDB。我喜欢将数据库中某些记录的访问限制为特定角色的想法;但是,我在文档中找不到如何执行此操作。我是 OrientDB 的新手,所以我确定我只是遗漏了一些东西。
这是我目前的情况。
// Create database.
ODatabaseDocumentTx db = new ODatabaseDocumentTx(path);
db.create();
// Create role with no permissions.
db.command(new OCommandSQL("INSERT INTO orole SET name = 'foobar', mode = 0;")).execute();
// Create a user with the new role.
OSecurity sm = db.getMetadata().getSecurity();
OUser user = sm.createUser("user", "user", "foobar");
ORole foobarRole = sm.getRole("foobar");
// Insert 2 records, one restricted, one is not.
OClass restricted = db.getMetadata().getSchema().getClass("ORestricted");
OClass docClass = db.getMetadata().getSchema().getOrCreateClass(TABLE_NAME, restricted);
ODocument doc1 = new ODocument(docClass);
ODocument doc2 = new ODocument(docClass);
// The restricted record...
doc1.field("name", TABLE_NAME);
doc1.field("Id", 1, OType.INTEGER);
doc1.field("Message", "Hello 1", OType.STRING);
doc1.save();
// The unrestricted record...
doc2.field("name", TABLE_NAME);
doc2.field("Id", 2, OType.INTEGER);
doc2.field("Message", "Hello 2", OType.STRING);
doc2.save();
// Allow "user" with "foobar" role to read record doc2.
String sql = String.format(
"UPDATE %s ADD _allowRead = %s",
doc2.getIdentity().toString(),
foobarRole.getDocument().getIdentity().toString());
db.command(new OCommandSQL(sql)).execute();
// Give foobar role permission to read from table.
db.command(new OCommandSQL(String.format("GRANT READ ON database.class.%s TO foobar", TABLE_NAME))).execute();
db.close();
// Open connection for "user".
ODatabaseDocumentTx userDb = new ODatabaseDocumentTx(path);
userDb.open("user", "user");
// Here I would expect to see the message from doc2 but not doc1.
// Nothing gets printed...
for (ODocument odoc : userDb.browseClass(TABLE_NAME))
{
System.out.println(odoc.field("Message"));
}
文档说在 READ 期间跳过角色无法访问的记录。就我而言,用户无法阅读任何内容。
关于如何使此行为起作用的任何想法?
经过几天的摆弄,这就是我让它工作的方式。
// Create database.
ODatabaseDocumentTx db = new ODatabaseDocumentTx(path);
db.create();
// Create users/roles.
OSecurity sm = db.getMetadata().getSecurity();
restrictedRole = sm.createRole("foobar", OSecurityRole.ALLOW_MODES.DENY_ALL_BUT);
restrictedRole.addRule(ORule.ResourceGeneric.CLASS, TABLE_NAME, ORole.PERMISSION_READ);
restrictedRole.addRule(ORule.ResourceGeneric.DATABASE, TABLE_NAME, ORole.PERMISSION_READ);
restrictedRole.addRule(ORule.ResourceGeneric.CLUSTER, TABLE_NAME, ORole.PERMISSION_READ);
restrictedRole.save();
restrictedRole.reload();
admin = sm.getUser("admin");
user2 = sm.createUser("user2", "user2", "foobar");
// Insert 2 records, one restricted, one is not.
OClass restricted = db.getMetadata().getSchema().getClass("ORestricted");
OClass docClass = db.getMetadata().getSchema().getOrCreateClass(TABLE_NAME, restricted);
ODocument doc1 = new ODocument(docClass);
ODocument doc2 = new ODocument(docClass);
// The restricted record...
doc1.field("name", TABLE_NAME);
doc1.field("Id", 1, OType.INTEGER);
doc1.field("Message", "Hello 1", OType.STRING);
doc1.save();
// The unrestricted record...
doc2.field("name", TABLE_NAME);
doc2.field("Id", 2, OType.INTEGER);
doc2.field("Message", "Hello 2", OType.STRING);
db.getMetadata().getSecurity().allowRole(doc2, OSecurityShared.ALLOW_READ_FIELD, "foobar");
doc2.save();
//
// PRINT RESTRICTED
//
db.close();
db = new ODatabaseDocumentTx(path);
db.open("user2", "user2");
// Prints:
// Hello 2
for (ODocument doc : db.browseClass(TABLE_NAME))
{
System.out.println(doc.field("Message"));
}
//
// PRINT ADMIN
//
db.close();
db = new ODatabaseDocumentTx(path);
db.open("admin", "admin");
// Prints:
// Hello 1
// Hello 2
for (ODocument doc : db.browseClass(TABLE_NAME))
{
System.out.println(doc.field("Message"));
}
角色的 addRule
方法允许具有该角色的用户从 class 中读取。第二个文档有一个带有 allowRole
的额外行,它允许具有该角色的用户阅读该特定文档,这是故意从第一个文档中删除的。结果是具有 "foobar" 角色的用户在阅读时只能获得第二个文档。管理员角色可以阅读这两个文档。
另外,请注意文档 class 继承自 "ORestricted"。
OClass restricted = db.getMetadata().getSchema().getClass("ORestricted");
OClass docClass = db.getMetadata().getSchema().getOrCreateClass(TABLE_NAME, restricted);
文档需要从 ORestricted
继承,以便记录级安全性起作用。就我个人而言,我没有在任何地方的代码中找到如何执行此操作的解释(也许我没有在正确的地方查找)并且 Java 中没有直接继承自 ORestricted
的文档 class class。所以我们必须使用模式 class 元数据来告诉驱动程序我们正在创建的文档需要继承自 ORestricted
.
我正在尝试 Record Level Security 使用文档数据库 (Java) API for OrientDB。我喜欢将数据库中某些记录的访问限制为特定角色的想法;但是,我在文档中找不到如何执行此操作。我是 OrientDB 的新手,所以我确定我只是遗漏了一些东西。
这是我目前的情况。
// Create database.
ODatabaseDocumentTx db = new ODatabaseDocumentTx(path);
db.create();
// Create role with no permissions.
db.command(new OCommandSQL("INSERT INTO orole SET name = 'foobar', mode = 0;")).execute();
// Create a user with the new role.
OSecurity sm = db.getMetadata().getSecurity();
OUser user = sm.createUser("user", "user", "foobar");
ORole foobarRole = sm.getRole("foobar");
// Insert 2 records, one restricted, one is not.
OClass restricted = db.getMetadata().getSchema().getClass("ORestricted");
OClass docClass = db.getMetadata().getSchema().getOrCreateClass(TABLE_NAME, restricted);
ODocument doc1 = new ODocument(docClass);
ODocument doc2 = new ODocument(docClass);
// The restricted record...
doc1.field("name", TABLE_NAME);
doc1.field("Id", 1, OType.INTEGER);
doc1.field("Message", "Hello 1", OType.STRING);
doc1.save();
// The unrestricted record...
doc2.field("name", TABLE_NAME);
doc2.field("Id", 2, OType.INTEGER);
doc2.field("Message", "Hello 2", OType.STRING);
doc2.save();
// Allow "user" with "foobar" role to read record doc2.
String sql = String.format(
"UPDATE %s ADD _allowRead = %s",
doc2.getIdentity().toString(),
foobarRole.getDocument().getIdentity().toString());
db.command(new OCommandSQL(sql)).execute();
// Give foobar role permission to read from table.
db.command(new OCommandSQL(String.format("GRANT READ ON database.class.%s TO foobar", TABLE_NAME))).execute();
db.close();
// Open connection for "user".
ODatabaseDocumentTx userDb = new ODatabaseDocumentTx(path);
userDb.open("user", "user");
// Here I would expect to see the message from doc2 but not doc1.
// Nothing gets printed...
for (ODocument odoc : userDb.browseClass(TABLE_NAME))
{
System.out.println(odoc.field("Message"));
}
文档说在 READ 期间跳过角色无法访问的记录。就我而言,用户无法阅读任何内容。
关于如何使此行为起作用的任何想法?
经过几天的摆弄,这就是我让它工作的方式。
// Create database.
ODatabaseDocumentTx db = new ODatabaseDocumentTx(path);
db.create();
// Create users/roles.
OSecurity sm = db.getMetadata().getSecurity();
restrictedRole = sm.createRole("foobar", OSecurityRole.ALLOW_MODES.DENY_ALL_BUT);
restrictedRole.addRule(ORule.ResourceGeneric.CLASS, TABLE_NAME, ORole.PERMISSION_READ);
restrictedRole.addRule(ORule.ResourceGeneric.DATABASE, TABLE_NAME, ORole.PERMISSION_READ);
restrictedRole.addRule(ORule.ResourceGeneric.CLUSTER, TABLE_NAME, ORole.PERMISSION_READ);
restrictedRole.save();
restrictedRole.reload();
admin = sm.getUser("admin");
user2 = sm.createUser("user2", "user2", "foobar");
// Insert 2 records, one restricted, one is not.
OClass restricted = db.getMetadata().getSchema().getClass("ORestricted");
OClass docClass = db.getMetadata().getSchema().getOrCreateClass(TABLE_NAME, restricted);
ODocument doc1 = new ODocument(docClass);
ODocument doc2 = new ODocument(docClass);
// The restricted record...
doc1.field("name", TABLE_NAME);
doc1.field("Id", 1, OType.INTEGER);
doc1.field("Message", "Hello 1", OType.STRING);
doc1.save();
// The unrestricted record...
doc2.field("name", TABLE_NAME);
doc2.field("Id", 2, OType.INTEGER);
doc2.field("Message", "Hello 2", OType.STRING);
db.getMetadata().getSecurity().allowRole(doc2, OSecurityShared.ALLOW_READ_FIELD, "foobar");
doc2.save();
//
// PRINT RESTRICTED
//
db.close();
db = new ODatabaseDocumentTx(path);
db.open("user2", "user2");
// Prints:
// Hello 2
for (ODocument doc : db.browseClass(TABLE_NAME))
{
System.out.println(doc.field("Message"));
}
//
// PRINT ADMIN
//
db.close();
db = new ODatabaseDocumentTx(path);
db.open("admin", "admin");
// Prints:
// Hello 1
// Hello 2
for (ODocument doc : db.browseClass(TABLE_NAME))
{
System.out.println(doc.field("Message"));
}
角色的 addRule
方法允许具有该角色的用户从 class 中读取。第二个文档有一个带有 allowRole
的额外行,它允许具有该角色的用户阅读该特定文档,这是故意从第一个文档中删除的。结果是具有 "foobar" 角色的用户在阅读时只能获得第二个文档。管理员角色可以阅读这两个文档。
另外,请注意文档 class 继承自 "ORestricted"。
OClass restricted = db.getMetadata().getSchema().getClass("ORestricted");
OClass docClass = db.getMetadata().getSchema().getOrCreateClass(TABLE_NAME, restricted);
文档需要从 ORestricted
继承,以便记录级安全性起作用。就我个人而言,我没有在任何地方的代码中找到如何执行此操作的解释(也许我没有在正确的地方查找)并且 Java 中没有直接继承自 ORestricted
的文档 class class。所以我们必须使用模式 class 元数据来告诉驱动程序我们正在创建的文档需要继承自 ORestricted
.