问题
当我在应用程序客户端的类中注入 @EJB 代理Main
,并且 EJB 有一个方法要求用户具有特定角色时,应用程序客户端容器 (ACC) 将要求用户尽快登录应用程序客户端启动。ACC 不会区分客户端考虑调用的方法,因此客户端实际上需要哪些角色(如果有的话)。实际上,这意味着我的客户端无法正确连接到服务器,如果只是 EJB 的一个单一方法具有一个需要特定角色的方法。如果我们显式地用@PermitAll
. ACC 仍然会提示输入用户名和密码,如果没有给出,那么我的 GlassFish 3.1.2.2 (build 5) 实现将中止一切并说“用户取消了身份验证”。
设置你的测试环境!
像这样声明一个远程接口:
@Remote
public interface IRemoteEJB
{
String echoGuest(String returnMe);
String echoAdmin(String returnMe);
}
编写EJB(我的问题与单例有关,所以我不敢在这里使用另一个会话注释!):
@Singleton
/*
* See the following annotation. We explicitly "permit all" on class level.
* Should not cause any ambiguity at all!
*/
@PermitAll
public class myEJB implements IRemoteEJB
{
@Override
public String echoGuest(String returnMe) {
return returnMe; }
@Override
// ..but here we grant access only to administrators:
@RolesAllowed("admin")
public String echoAdmin(String returnMe) {
return returnMe; }
}
至于客户端部分,这是我能想到的最小可能的实现:
public class Main
{
@EJB private static remoteProxy;
public static void main(String... args)
{
String reply = remoteProxy.echoGuest("Hello world!");
JOptionPane.showMessageDialog(null, reply);
}
}
结果
您认为客户端成功地对该echoGuest
方法进行了“匿名”调用吗?不,我发现 ACC 甚至会在@EJB
注入之前强制客户端提供用户名和密码。简单地说,如果我们不能混合从应用程序客户端到 EJB 的访问身份验证。上面的解决方案是从方法中删除@RolesAllowed("admin")
注释echoAdmin
。
从某种意义上说,这完全有道理。ACC 仅在客户端启动期间处于活动状态,这正是我们需要将所有注入的资源放在应用程序客户端中的原因,无论是在类中还是在Main
类中static
。ACC 根本无法确切知道 EJB 中的哪些方法将被调用。
好的,但这不会破坏@PermitAll
和@RolesAllowed
注释的规范和预期行为吗?世界上没有任何方法可以为应用程序客户端提供匿名访问 EJB 的权限,该 EJB 只有一个过时的、从未调用过的需要特定角色的方法?到目前为止,我不仅必须将这些方法与我认为可以而且应该做的注释分开,而且我还必须重构逻辑以完全分开 EJB:s。感觉很难:'(