0

问题

当我在应用程序客户端的类中注入 @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。感觉很难:'(

4

1 回答 1

0

The Java EE 7 specification JSR 342 says on page 9, that application client's deployment and management is not completely defined by this specification. Thus we can expect different, non-portable behavior when it comes to the "management" of application clients.

The specification continues and talk about Lazy Authentication on pages 41 and 42:

There is a cost associated with authentication. For example, an authentication process may require exchanging multiple messages across the network. Therefore, it is desirable to use lazy authentication, that is, to perform authentication only when it is needed. With lazy authentication, a user is not required to authenticate until there is a request to access a protected resource.

Lazy authentication can be used with first-tier clients (applets, application clients) when they request access to protected resources that require authentication.

I cannot parse this quote and judge whether Lazy Authentication is required by the specification or not. Apparently, it is not. That is, GlassFish do not break any rule when he require authentication from our application client even before we accessed the protected resource (a method invocation in the example).

Moreover, the specification really hit where it hurts on page 44:

The techniques used may vary with the implementation of the application client container, and are beyond the control of the application

Thus my final judgement must be that the specification does not require lazy authentication and that "techniques" may vary.

于 2013-06-13T13:47:52.440 回答