10

I'm developing a Java EE 6 application using Glassfish 3.1, B06. To secure my app, i'm using a JDBCRealm and programmatic security. This works fine to check username and password. But when it comes to declaring security roles, i have a problem:

To use Security Roles in Java EE 6, i have to declare those roles both in the EJB deployment descriptor and in the Glassfish-specific deployment descriptor to link those roles (as explained in the Java EE 6-tutorial) Only than i can use the method isCallerInRole(String roleRef) inside an EJB to check permissions.

This is not desirable for my application, as i want that its possible to add Security roles both dynamically and programmatically, without having to write XML files (and for example make it possible to define role names in a database).

I just debugged through the GF3-source code and saw the implementation of isCallerInRole in com.sun.ejb.containers.EjbContextImpl. There the container gets the roles out of the EJB descriptor:

public boolean isCallerInRole(String roleRef) {
  (...)
  EjbDescriptor ejbd = container.getEjbDescriptor();
  RoleReference rr = ejbd.getRoleReferenceByName(roleRef);
  (...)
}

I looked around and found out that if i could somehow get the EJB descriptor inside my application, i could add a role like this:

EjbDescriptor ejbd = //??? Can i use that descriptor inside my app, or is that "forbidden"?
RoleReference rr = new RoleReference("admin", "Admins are allowed to do everything");
ejbd.addRoleReference(rr);

Anyone did something like this, or got some thoughts about it? Is it possible to use the Ejb deployment descriptor inside my application? Or are there better approaches?

P.S. or should i use MBeans to add Roles? Found a quite related post here.

4

2 回答 2

3

我想出了以下解决方案,以在登录后以编程方式添加角色,该解决方案至少适用于 GlassFish 3.1.2 build 23。

import com.sun.enterprise.security.SecurityContext;
import com.sun.enterprise.security.web.integration.PrincipalGroupFactory;
import java.security.Principal;
import java.util.Set;
import javax.security.auth.Subject;
import org.glassfish.security.common.Group;

public class GlassFishUtils {
    public static void addGroupToCurrentUser(String groupName, String realmName) {
        Subject subject = SecurityContext.getCurrent().getSubject();
        Set<Principal> principals = subject.getPrincipals();
        Group group = PrincipalGroupFactory.getGroupInstance(groupName, realmName);
        if (!principals.contains(group))
            principals.add(group);
    }
}

您需要将GlassFishsecurity.jarcommon-util.jar从 GlassFish 添加到您的项目库中。

并且不要忘记<security-role>在您的 web.xml 中为您希望添加的角色创建一个部分。

请注意,我使用的功能似乎不是已发布的稳定 API 的一部分,因此无法保证这将在 GlassFish 的未来版本中继续工作。

sun.appserv.security.AppservPasswordLoginModule.commit()我从GlassFish的源代码中获得了有关如何添加角色的信息。如果将来的 GlassFish 版本破坏了我的代码,这个函数将是一个很好的起点,以便找出如何修复它。

于 2012-07-11T08:04:14.983 回答
3

Javadoc 确实明确提到了这个要求:

   /**
    * Tests if the caller has a given role.
    *
    * @param roleName - The name of the security role. The role must be one of the security roles that
    * is defined in the deployment descriptor.
    * @return True if the caller has the specified role.
    */
   public boolean isCallerInRole(String roleName);

但是,我发现至少对于 JBoss AS,根本不需要提前声明这些角色。在我们的例子中,主要角色是在系统中动态创建的,并在进行身份验证时分配。因此,不可能预先声明这些。

然而,isCallerInRole 方法运行良好。

我意识到切换到 JBoss AS 不是一个解决方案,但也许这些信息对某人来说还是有价值的。

于 2011-02-12T19:06:19.217 回答