作者:
解码DACS 锁的方法和示例
当使用OpenDACS API和基于内容的授权服务时,API以AuthorizationAgent.checkSubscription()方法的形式,鼓励将DACS 锁作为不透明的数据元素来处理,以保持松散的耦合。
那么,为什么我们要将DACS 锁解码成其组成部分呢?
在回答这个问题之前,让我们从RefreshMsg的一个例子开始,研究一下DACS 锁的内部结构。
RefreshMsg
streamId="5"
domain="MarketPrice Domain"
solicited
RefreshComplete
state="Open / Ok / None / 'All is well'"
itemGroup="00 01"
permissionData="03 01 01 65 62 c0"
name="TRI.N"
nameType="1"
serviceId="257"
serviceName="ELEKTRON_DD"
Payload dataType="FieldList"
FieldList FieldListNum="79" DictionaryId="1"
FieldEntry fid="1" name="PROD_PERM" dataType="UInt" value="6562"
FieldEntry fid="2" name="RDNDISPLAY" dataType="UInt" value="64"
FieldEntry fid="3" name="DSPLY_NAME" dataType="Rmtes" value="THOMSON REUTERS"
FieldEntry fid="4" name="RDN_EXCHID" dataType="Enum" value="2"
FieldEntry fid="6" name="TRDPRC_1" dataType="Real" value="44.16"
…
RefreshMsg包含的permissionData="03 01 01 65 62 c0 "就是DACS 锁。
DACS 锁的结构在RFA C++ DACSLOCK API Developers Guide 开发者指南中有所描述,上列中permissionData显示的DACS 锁的组成部分是:
Version | ServiceID | PE | End |
3 | 01 01 | 65 62 | c0 |
ServiceID服务编号用十六进制编码,DACS 服务定义和基础设施配置中定义的值对应成十进制就是:0101 = 257
这是原始服务,因此在此实例中映射到与请求相同的服务名称:"ELEKTRON_DD"。
PE值是二进制编码的十进制,例中对应的十进制值就是65 62=6562。对于更复杂的DACS 锁,可以有额外的PE值和运算符(AND/OR),指定如何应用PE值组合的要求。
对于复合服务器提供的服务,即它结合了数据、增加了一些价值或提供了一些来自另一个服务数据的衍生计算,那么DACS 锁可能包含来自原始服务的额外服务编号和PE组合。这就是所谓的复合锁。每当你对DACS锁使用checkSubscription()方法时,API就会根据锁中存储的每个原始服务及其相关的PE值来验证用户的权利;这可以保持正确的数据访问控制,同时减少管理负担,因为用户只需要有权使用原始服务。
DACS锁解码示例
当数据存储在另一个系统中时,例如数据库,其中的一个挑战是如何在保持正确的数据访问控制的同时允许对数据进行搜索表达。
一个解决方案是提取用户权限配置文件数据并将其包含在表达式中,这样提供的结果集就基于存储的数据和用户权限。
要做到这一点,我们首先需要访问用户权限简介,这可以通过AuthorizationAgent::getPEList()方法获得。
rfa::dacs::AuthorizationAgent::getPEList(
const rfa::common::Handle & handle,
const rfa::common::RFA_String & sServiceName,
const rfa::common::RFA_String & sPEFilter,
rfa::common::RFA_Vector<unsigned long> & vPEList)
当成功时,vPEList参数将被填充到分配给与句柄相关的用户的sServiceName的PE列表中。
这个解决方案的第二部分需要DACS锁中的PE值,这就是解码变得有用的地方。解码后的DACS锁必须与它所关联的数据一起存储,例如
DSPLY_NAME | RDN_EXCHID | TRDPRC_1 | HIGH_1 | Service | PE |
"THOMSON REUTERS" | NYS (2) | 44.16 | 44.17 | ELEKTRON_DD | 6562 |
你可能会考虑使用PROD_PERM字段来访问PE值的做法,正如你在上面的例子中所看到的,它持有相同的值,然而PROD_PERM字段不能代表上述DACS锁中可能出现的任何变体;另外,DACS锁中的原始服务不一定与请求中的服务名称或服务编号相匹配,这将取决于基础设施的配置。
现在,使用一个包含getPEList数据的表和添加到数据表中的DACS锁信息,如上图所示,这两个表的JOIN语句可以产生一个用户有权访问的结果集。
DACS锁解码示例——Java版本
下面的代码将提取存储在DACS锁中的服务、操作员和PE值,它可以在EMA或RFA消费者中使用。Open DACS API包含在RFA中,所以要在EMA应用中使用Open DACS,你需要包含RFA库:rfa.jar
首先,当我们收到一个刷新信息时,我们必须检查是否有DACS锁存在,然后才提取它。
if( refreshMsg.hasPermissionData()) // Always check before accessing
{
System.out.print("hasPermissionData: ");
// Get the raw DACS lock.
java.nio.ByteBuffer bufPerm = refreshMsg.permissionData();
byte[] byteBuf = new byte[bufPerm.limit()-bufPerm.position()];
bufPerm.get(byteBuf);
使用原始DACS锁创建一个AuthorizationLock...
try {
String lockStr=" ";
//Create an AuthorizationLock from the raw DACS Lock.
AuthorizationLock authLock = new AuthorizationLock(byteBuf);
// Get the lock with serviceIDs
AuthorizationLockResult alr =
AuthorizationLockUtility.getStructuredServiceIDLock(authLock);
检查使用AuthorizationLockUtility从AuthorizationLock获得StructuredServiceIDLock的结果...
// Check the result
if( AuthorizationLockResult.VALID == alr.getState() &&
AuthorizationLockResult.SUCCESS == alr.getStatusCode())
{
我们需要使用AuthorizationLockResult .getData()来获取AuthorizationStructuredServiceIDLock,但在使用cast之前要确保AuthorizationLockResult有正确的类型。
// Make sure it is a AuthorizationStructuredServiceIDLock before casting.
if( alr.getType() ==
AuthorizationLockResult.AS_AuthorizationStructuredServiceIDLock )
{
AuthorizationStructuredServiceIDLock[] aAssil =
(AuthorizationStructuredServiceIDLock[])alr.getData();
现在我们可以开始迭代锁中的每个服务项目了...
// for each service in the lock get its associated PEs and operator.
for( AuthorizationStructuredServiceIDLock assil : aAssil )
{
lockStr = "SId=";
lockStr += Integer.toString(assil.getServiceID());
lockStr += " Op=";
if ( assil.getOperator() == AuthorizationLock.OR )
lockStr += "OR ";
else if ( assil.getOperator() == AuthorizationLock.AND )
lockStr += "AND ";
一旦我们有了这个条目的serviceId和操作者,我们就可以访问它的列表PE......
long[] peList = assil.getPEList();
if( peList != null && peList.length>0 )
{
lockStr += "PE=";
for( long pe : peList )
{
lockStr += Long.toString(pe);
lockStr +=" ";
}
}
} // repeat for the next AuthorizationStructuredServiceIDLock entry
最后,报告结果...
} // else AuthorizationLockResult indicates incorrect type
else
System.err.println("Unable to decode StructuredServiceIDLock");
}
System.out.println("PermData = "+lockStr);
} catch (AuthorizationException e) {
System.err.println("AuthorizationException");
e.printStackTrace();
System.exit(-1);
}
} // end of permissionData processing
对于前面给出的RefreshMsg例子,你应该看到上面的代码为DACS锁给出的报告如下:
hasPermissionData: PermData = SId=257 Op=AND PE=6562
结论
使用上面描述的Open DACS的功能,并保留解码后的DACS锁信息,即使在使用SQL或搜索表达式从数据存储中提取时,也可以保持DACS管理员定义的访问控制。