问题:java rmi认证和安全。 exportObject使它公开?
当你UnicastRemoteObject.exportObject(instance)
。现在这个实例是否可以公开提供给所有客户?即使需要一点棘手来找到它的端口。
情况是这样的:
我有一个Java RMI客户端/服务器安装,我想添加一些验证。允许客户端在任何其他RPC调用工作之前使用用户/传递组合。
我在网上发现了一个简单的建议,起初看起来像个好主意。
interface LoginService implements Remote {
public MainService login(String username, char[] password) throws RemoteException;
}
interface MainService implements Remote {
/* all my real rpc calls go here */
}
这个想法是,创建一个远程对象来体现RPC的后验证访问。并通过执行身份验证的第一层访问它。
LoginServiceImpl.login()
必须看起来像这样。
public MainService login(String username, char[] password) throws RemoteException {
/* verify username and password */
MainService service = new MainServiceImpl();
MainService stub = UnicastRemoteObject.exportObject(service, 0);
return stub;
}
因此,每个调用login()
客户获得的MainService
自己专用的远程实例。当然,我会把所有东西都包装在ssl中以保护纯文本密码。
这就是问题所在:
看来,我出口我的新MainServiceImpl
实例,其已经公开,后。知道要查找什么的任何其他客户端可以连接到该实例并在该实例上拨打电话。
我在创建它之后必须导出MainService,否则RMI将不会将存根发送到客户端。相反,它会尝试序列化MainService实例。
我可以将用户名粘在MainService
上,但这实际上无助于此。
这是一个很好的解决方案,但其棘手。 它很容易将rmi包装在SSL中。在允许访问重要的RMI对象之前,它很容易在ssl连接中使用RMI进行认证。您甚至可以设置该随机端口系统属性来提高所选端口的安全性。 但最后,我怀疑你仍然可以扫描正确的端口。 因此,唯一有用的解决方案似乎是做一些像本答案中建议的解决方案一样低的级别,或者在每个RMI请求(在ssl流内)上发送auth令牌。 – DragonFax 2009-11-06 09:47:05
@DragonFax:使用客户端身份验证的SSL是您的第一句话的反例。扫描正确的端口对你没有任何好处,除非你也可以猜出ObjectID,正如你注意的那样,它可以被加密地随机化。 – EJP 2011-07-11 08:22:57