You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomee.apache.org by ndegraev <ni...@telenet.be> on 2011/02/03 08:24:09 UTC

JUnit: Sessioncontext.isCallerInRole allways returns false

I need to write a session bean that somewhere in the code checks if the
current user has some role(s).

To unittest my EJB3 I'm trying out OpenEJB. I followed the example about
testing security but if I test in my code for the role with
SessionContect.isCallerInRole() it always returns false.

Why doesn't it work?

I've written some code to illustrate.

My local interface:

@Local
public interface MyBean {

    boolean doSomething();

}

My EJB:

@Stateless
public class MyBeanImpl implements MyBean {

    @Resource
    private SessionContext sessionContext;

    @Override
    public boolean doSomething() {
        return this.sessionContext.isCallerInRole("role1");
    }

}

My test:

public class MyBeanTest {

    private Context context;

    @Before
    public void setUp() throws Exception {
        final Properties properties = new Properties();
        properties.put(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.openejb.client.LocalInitialContextFactory");

        this.context = new InitialContext(properties);
    }

    @Test
    public void test1() throws Exception {
        final Caller roleBean = (Caller)
this.context.lookup("RoleBeanLocal");
        roleBean.call(new Callable() {

            @Override
            public Object call() throws Exception {
                final MyBean myBean = (MyBean)
MyBeanTest.this.context.lookup("MyBeanImplLocal");
                Assert.assertTrue(myBean.doSomething()); // FAILURE
                return null;
            }
        });
    }

    @Test
    public void test2() throws Exception {
        final Caller role2Bean = (Caller)
this.context.lookup("Role2BeanLocal");
        role2Bean.call(new Callable() {

            @Override
            public Object call() throws Exception {
                final MyBean myBean = (MyBean)
MyBeanTest.this.context.lookup("MyBeanImplLocal");
                Assert.assertFalse(myBean.doSomething());
                return null;
            }
        });
    }

    public static interface Caller {

        <V> V call(Callable<V> callable) throws Exception;

    }

    @Stateless
    @RunAs("role1")
    public static class RoleBean implements Caller {

        @Override
        public <V> V call(final Callable<V> callable) throws Exception {
            return callable.call();
        }

    }

    @Stateless
    @RunAs("role2")
    public static class Role2Bean implements Caller {

        @Override
        public <V> V call(final Callable<V> callable) throws Exception {
            return callable.call();
        }

    }
}


-- 
View this message in context: http://openejb.979440.n4.nabble.com/JUnit-Sessioncontext-isCallerInRole-allways-returns-false-tp3257408p3257408.html
Sent from the OpenEJB User mailing list archive at Nabble.com.

Re: JUnit: Sessioncontext.isCallerInRole allways returns false

Posted by ndegraev <ni...@telenet.be>.
It never occured to me it might be a bug. I thought I was just missing
something. :-) 

Thanks for the new project.

Just to let you know that all roles I want to test must be mentioned in the
@RolesAllowed.
The test method below only succeeds if @RolesAllowed({ "admins", "users" })
is set on the EJB.

    @Test
    public void test1() throws NamingException {
        ISayHelloServiceLocal ibean;

        ibean = TestUtils.interfaceLookup(TestUtils.getCtx("user",
"user_pass"), ISayHelloServiceLocal.class);
        Assert.assertEquals("user", ibean.getUserName());
        Assert.assertFalse(ibean.isCallerAdmin());
        Assert.assertFalse(ibean.hasRole("admins"));
        Assert.assertTrue(ibean.hasRole("users"));

        ibean = TestUtils.interfaceLookup(TestUtils.getCtx("admin",
"admin_pass"), ISayHelloServiceLocal.class);
        Assert.assertEquals("admin", ibean.getUserName());
        Assert.assertTrue(ibean.isCallerAdmin());
        Assert.assertTrue(ibean.hasRole("admins"));
        Assert.assertFalse(ibean.hasRole("users"));
    }


-- 
View this message in context: http://openejb.979440.n4.nabble.com/JUnit-Sessioncontext-isCallerInRole-allways-returns-false-tp3257408p3275888.html
Sent from the OpenEJB User mailing list archive at Nabble.com.

Re: JUnit: Sessioncontext.isCallerInRole allways returns false

Posted by Thiago Veronezi <th...@veronezi.org>.
Hi!
It seems that you just found a bug. :O) If you add a dummy method with the
"RolesAllowed" annotation, your methods get back to work. I've changed the
example to fit your needs. Ill investigate this problem later today, in the
meantime you can use this workaround. Check the new example here:

http://people.apache.org/~tveronezi/security.zip

[]s,
Thiago

On Tue, Feb 8, 2011 at 6:24 AM, ndegraev <ni...@telenet.be> wrote:

>
> Thanks for the project. When I run it's as expected.
>
> Now I'm trying to apply your examples on my test project and it fails. I
> don't know why. It's probably something small but I just don't see it. Can
> you have a look?
>
> MyTest.java:
>
> @Local
> public interface MyTest {
>
>    boolean hasRole(String role);
>
>    boolean isCallerAdmin();
>
> }
>
> MyTestBean.java:
>
> @Stateless
> public class MyTestBean implements MyTest {
>
>    @Resource
>    private SessionContext sessionContext;
>
>    public boolean hasRole(final String role) {
>        return this.sessionContext.isCallerInRole(role);
>    }
>
>    public boolean isCallerAdmin() {
>        return this.sessionContext.isCallerInRole("admins");
>    }
>
> }
>
> MyTestCase.java:
>
> public class MyTestCase {
>
>    @Before
>    public void setUp() throws Exception {
>         final ClassLoader contextClassLoader =
> Thread.currentThread().getContextClassLoader();
>        final URL resource = contextClassLoader.getResource("login.config");
>         System.setProperty("java.security.auth.login.config",
> resource.toExternalForm());
>
>         final Properties properties = new Properties();
>         properties.setProperty("openejb.authentication.realmName",
> "PropertiesLogin");
>        new InitialContext(properties);
>    }
>
>    @Test
>    public void test1() throws NamingException {
>        System.out.println("test 1...");
>        final Context ctx = getCtx("user", "user_pass");
>        final MyTest myTest = (MyTest) ctx.lookup("MyTestBeanLocal");
>        System.out.println("Is admin? " + myTest.isCallerAdmin());
>        System.out.println("Is in 'admins'? " + myTest.hasRole("admins"));
>        System.out.println("Is in 'users'? " + myTest.hasRole("users"));
>    }
>
>    @Test
>    public void test2() throws NamingException {
>        System.out.println("test 2...");
>        final Context ctx = getCtx("admin", "admin_pass");
>        final MyTest myTest = (MyTest) ctx.lookup("MyTestBeanLocal");
>        System.out.println("Is admin? " + myTest.isCallerAdmin());
>        System.out.println("Is in role 'admins'? " +
> myTest.hasRole("admins"));
>        System.out.println("Is in role 'users'? " +
> myTest.hasRole("users"));
>    }
>
>    private Context getCtx(final String user, final String pass) throws
> NamingException {
>         final Properties properties = new Properties();
>         properties.setProperty(Context.SECURITY_PRINCIPAL, user);
>        properties.setProperty(Context.SECURITY_CREDENTIALS, pass);
>        return new InitialContext(properties);
>    }
>
> }
>
> groups.properties, users.properties, login.config and jndi.properties are
> copied over from your project.
>
> When I run it I get this output:
>
> Apache OpenEJB 3.1.4    build: 20101112-03:32
> http://openejb.apache.org/
> INFO - openejb.home = C:\dvl\test-openejb
> INFO - openejb.base = C:\dvl\test-openejb
> INFO - Configuring Service(id=Default Security Service,
> type=SecurityService, provider-id=Default Security Service)
> INFO - Configuring Service(id=Default Transaction Manager,
> type=TransactionManager, provider-id=Default Transaction Manager)
> INFO - Found EjbModule in classpath: C:\dvl\test-openejb\target\classes
> INFO - Beginning load: C:\dvl\test-openejb\target\classes
> INFO - Configuring enterprise application: classpath.ear
> INFO - Configuring Service(id=Default Stateless Container, type=Container,
> provider-id=Default Stateless Container)
> INFO - Auto-creating a container for bean MyTestBean:
> Container(type=STATELESS, id=Default Stateless Container)
> INFO - Using 'openejb.validation.output.level=VERBOSE'
> INFO - Enterprise application "classpath.ear" loaded.
> INFO - Assembling app: classpath.ear
> INFO - Jndi(name=MyTestBeanLocal) --> Ejb(deployment-id=MyTestBean)
> INFO - Created Ejb(deployment-id=MyTestBean, ejb-name=MyTestBean,
> container=Default Stateless Container)
> INFO - Deployed Application(path=classpath.ear)
> test 1...
> INFO - Logging in
> Is admin? false
> Is in 'admins'? false
> Is in 'users'? false
> test 2...
> INFO - Logging in
> Is admin? false
> Is in role 'admins'? false
> Is in role 'users'? false
> --
> View this message in context:
> http://openejb.979440.n4.nabble.com/JUnit-Sessioncontext-isCallerInRole-allways-returns-false-tp3257408p3275679.html
> Sent from the OpenEJB User mailing list archive at Nabble.com.
>

Re: JUnit: Sessioncontext.isCallerInRole allways returns false

Posted by ndegraev <ni...@telenet.be>.
Thanks for the project. When I run it's as expected.

Now I'm trying to apply your examples on my test project and it fails. I
don't know why. It's probably something small but I just don't see it. Can
you have a look?

MyTest.java:

@Local
public interface MyTest {

    boolean hasRole(String role);

    boolean isCallerAdmin();

}

MyTestBean.java:

@Stateless
public class MyTestBean implements MyTest {

    @Resource
    private SessionContext sessionContext;

    public boolean hasRole(final String role) {
        return this.sessionContext.isCallerInRole(role);
    }

    public boolean isCallerAdmin() {
        return this.sessionContext.isCallerInRole("admins");
    }

}

MyTestCase.java:

public class MyTestCase {

    @Before
    public void setUp() throws Exception {
        final ClassLoader contextClassLoader =
Thread.currentThread().getContextClassLoader();
        final URL resource = contextClassLoader.getResource("login.config");
        System.setProperty("java.security.auth.login.config",
resource.toExternalForm());

        final Properties properties = new Properties();
        properties.setProperty("openejb.authentication.realmName",
"PropertiesLogin");
        new InitialContext(properties);
    }

    @Test
    public void test1() throws NamingException {
        System.out.println("test 1...");
        final Context ctx = getCtx("user", "user_pass");
        final MyTest myTest = (MyTest) ctx.lookup("MyTestBeanLocal");
        System.out.println("Is admin? " + myTest.isCallerAdmin());
        System.out.println("Is in 'admins'? " + myTest.hasRole("admins"));
        System.out.println("Is in 'users'? " + myTest.hasRole("users"));
    }

    @Test
    public void test2() throws NamingException {
        System.out.println("test 2...");
        final Context ctx = getCtx("admin", "admin_pass");
        final MyTest myTest = (MyTest) ctx.lookup("MyTestBeanLocal");
        System.out.println("Is admin? " + myTest.isCallerAdmin());
        System.out.println("Is in role 'admins'? " +
myTest.hasRole("admins"));
        System.out.println("Is in role 'users'? " +
myTest.hasRole("users"));
    }

    private Context getCtx(final String user, final String pass) throws
NamingException {
        final Properties properties = new Properties();
        properties.setProperty(Context.SECURITY_PRINCIPAL, user);
        properties.setProperty(Context.SECURITY_CREDENTIALS, pass);
        return new InitialContext(properties);
    }

}

groups.properties, users.properties, login.config and jndi.properties are
copied over from your project.

When I run it I get this output:

Apache OpenEJB 3.1.4    build: 20101112-03:32
http://openejb.apache.org/
INFO - openejb.home = C:\dvl\test-openejb
INFO - openejb.base = C:\dvl\test-openejb
INFO - Configuring Service(id=Default Security Service,
type=SecurityService, provider-id=Default Security Service)
INFO - Configuring Service(id=Default Transaction Manager,
type=TransactionManager, provider-id=Default Transaction Manager)
INFO - Found EjbModule in classpath: C:\dvl\test-openejb\target\classes
INFO - Beginning load: C:\dvl\test-openejb\target\classes
INFO - Configuring enterprise application: classpath.ear
INFO - Configuring Service(id=Default Stateless Container, type=Container,
provider-id=Default Stateless Container)
INFO - Auto-creating a container for bean MyTestBean:
Container(type=STATELESS, id=Default Stateless Container)
INFO - Using 'openejb.validation.output.level=VERBOSE'
INFO - Enterprise application "classpath.ear" loaded.
INFO - Assembling app: classpath.ear
INFO - Jndi(name=MyTestBeanLocal) --> Ejb(deployment-id=MyTestBean)
INFO - Created Ejb(deployment-id=MyTestBean, ejb-name=MyTestBean,
container=Default Stateless Container)
INFO - Deployed Application(path=classpath.ear)
test 1...
INFO - Logging in
Is admin? false
Is in 'admins'? false
Is in 'users'? false
test 2...
INFO - Logging in
Is admin? false
Is in role 'admins'? false
Is in role 'users'? false
-- 
View this message in context: http://openejb.979440.n4.nabble.com/JUnit-Sessioncontext-isCallerInRole-allways-returns-false-tp3257408p3275679.html
Sent from the OpenEJB User mailing list archive at Nabble.com.

Re: JUnit: Sessioncontext.isCallerInRole allways returns false

Posted by Thiago Veronezi <th...@veronezi.org>.
Hi,
I'm glad to hear that. An example says more than a thousand words, so check
this code I've implemented for you here...

http://dl.dropbox.com/u/1459144/security.zip

It is doing exactly what you want.

[]s,
Thiago.


On Fri, Feb 4, 2011 at 10:37 AM, ndegraev <ni...@telenet.be> wrote:

>
> That was really helpful! Thanks. But wait, I'm not there yet...
>
> I decided to use PropertiesLoginModule and now I can login.
>
> I defined the roles I want to use in my unit tests in ejb-jar.xml:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <j2ee:ejb-jar
>                version="3.0"
>                xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"
>                xmlns:xml="http://www.w3.org/XML/1998/namespace"
>                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>                xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
> http://java.sun.com/xml/ns/j2ee/ejb-jar_3_0.xsd ">
>
>        <j2ee:assembly-descriptor>
>                <j2ee:security-role>
>                        <j2ee:role-name>role1</j2ee:role-name>
>                </j2ee:security-role>
>                <j2ee:security-role>
>                        <j2ee:role-name>role2</j2ee:role-name>
>                </j2ee:security-role>
>        </j2ee:assembly-descriptor>
>
> </j2ee:ejb-jar>
>
> Where do I put this? In src/main/resources/META-INF,
> src/test/resources/META-INF or both?
>
> And where do I map my JAAS groups to J2EE roles? Probably in the
> openejb-jar.xml?
>
> Not a lot of documentation on how to do it, though, so any help is welcome.
>
> --
> View this message in context:
> http://openejb.979440.n4.nabble.com/JUnit-Sessioncontext-isCallerInRole-allways-returns-false-tp3257408p3260388.html
> Sent from the OpenEJB User mailing list archive at Nabble.com.
>

Re: JUnit: Sessioncontext.isCallerInRole allways returns false

Posted by ndegraev <ni...@telenet.be>.
That was really helpful! Thanks. But wait, I'm not there yet...

I decided to use PropertiesLoginModule and now I can login. 

I defined the roles I want to use in my unit tests in ejb-jar.xml:

<?xml version="1.0" encoding="UTF-8"?>
<j2ee:ejb-jar 
		version="3.0" 
		xmlns:j2ee="http://java.sun.com/xml/ns/j2ee" 
		xmlns:xml="http://www.w3.org/XML/1998/namespace" 
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
		xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/ejb-jar_3_0.xsd ">

	<j2ee:assembly-descriptor>
		<j2ee:security-role>
			<j2ee:role-name>role1</j2ee:role-name>
		</j2ee:security-role>
		<j2ee:security-role>
			<j2ee:role-name>role2</j2ee:role-name>
		</j2ee:security-role>
	</j2ee:assembly-descriptor>
		
</j2ee:ejb-jar>

Where do I put this? In src/main/resources/META-INF,
src/test/resources/META-INF or both?

And where do I map my JAAS groups to J2EE roles? Probably in the
openejb-jar.xml? 

Not a lot of documentation on how to do it, though, so any help is welcome.

-- 
View this message in context: http://openejb.979440.n4.nabble.com/JUnit-Sessioncontext-isCallerInRole-allways-returns-false-tp3257408p3260388.html
Sent from the OpenEJB User mailing list archive at Nabble.com.

Re: JUnit: Sessioncontext.isCallerInRole allways returns false

Posted by Thiago Veronezi <th...@veronezi.org>.
Hi,
You can use a custom "login.config". To load this custom file, you can use
the "System.setProperty" method...

final ClassLoader ctxCl = Thread.currentThread().getContextClassLoader();
URL resource = ctxCl.getResource("login.config");
System.setProperty("java.security.auth.login.config",
resource.toExternalForm());

Your custom "login.config" could be something like..

SQLLogin {
    org.apache.openejb.core.security.jaas.SQLLoginModule required
     jdbcURL="jdbc:hsqldb:hsql://localhost/xdb"
     userSelect="SELECT account, '1234' FROM user WHERE account = ?"
     groupSelect="SELECT u.account, ur.role FROM user AS u, user_roles AS ur
WHERE u.uid = ur.user_id AND u.account = ?";
};

...
And to get your initial context...


final Properties props = new Properties();
props.setProperty(Context.SECURITY_PRINCIPAL, user);
props.setProperty(Context.SECURITY_CREDENTIALS, "1234");
props.setProperty("openejb.authentication.realmName", "SQLLogin");
return new InitialContext(props);

This way you make a connection to your embedded openejb server using the
"user" account.
Check this link for more info about jaas...

http://openejb.apache.org/3.0/security.html

[]s,
Thiago.


On Thu, Feb 3, 2011 at 9:41 AM, ndegraev <ni...@telenet.be> wrote:

>
> Ah, pity.
>
> How would I then best test functionality which relies on the caller
> Principal?
>
> What I'm planning to do is create a class that implements SessionContext
> and
> on which I can set roles. The isCallerInRoles() will check the parameter
> against the set roles. Via reflection I then set this context on my EJB for
> the tests.
>
> Do you know a better way?
>
> Thanks,
>
> Nick
> --
> View this message in context:
> http://openejb.979440.n4.nabble.com/JUnit-Sessioncontext-isCallerInRole-allways-returns-false-tp3257408p3258218.html
> Sent from the OpenEJB User mailing list archive at Nabble.com.
>

Re: JUnit: Sessioncontext.isCallerInRole allways returns false

Posted by ndegraev <ni...@telenet.be>.
Ah, pity.

How would I then best test functionality which relies on the caller
Principal?

What I'm planning to do is create a class that implements SessionContext and
on which I can set roles. The isCallerInRoles() will check the parameter
against the set roles. Via reflection I then set this context on my EJB for
the tests.

Do you know a better way?

Thanks,

Nick
-- 
View this message in context: http://openejb.979440.n4.nabble.com/JUnit-Sessioncontext-isCallerInRole-allways-returns-false-tp3257408p3258218.html
Sent from the OpenEJB User mailing list archive at Nabble.com.

Re: JUnit: Sessioncontext.isCallerInRole allways returns false

Posted by Thiago Veronezi <th...@veronezi.org>.
Hi nick,
This is the default behaviour of EJB.

According to the EJB3.1 specs:

17.3.4.1: Run-as
Establishing a run-as identity for an enterprise bean does not affect the
identities of its callers, which are the identities tested for permission to
access the methods of the enterprise bean. The run-as identity establishes
the identity the enterprise bean will use when it makes calls.

[]s,
Thiago.


On Thu, Feb 3, 2011 at 3:24 AM, ndegraev <ni...@telenet.be> wrote:

>
> I need to write a session bean that somewhere in the code checks if the
> current user has some role(s).
>
> To unittest my EJB3 I'm trying out OpenEJB. I followed the example about
> testing security but if I test in my code for the role with
> SessionContect.isCallerInRole() it always returns false.
>
> Why doesn't it work?
>
> I've written some code to illustrate.
>
> My local interface:
>
> @Local
> public interface MyBean {
>
>    boolean doSomething();
>
> }
>
> My EJB:
>
> @Stateless
> public class MyBeanImpl implements MyBean {
>
>    @Resource
>    private SessionContext sessionContext;
>
>    @Override
>    public boolean doSomething() {
>        return this.sessionContext.isCallerInRole("role1");
>    }
>
> }
>
> My test:
>
> public class MyBeanTest {
>
>    private Context context;
>
>    @Before
>    public void setUp() throws Exception {
>        final Properties properties = new Properties();
>        properties.put(Context.INITIAL_CONTEXT_FACTORY,
> "org.apache.openejb.client.LocalInitialContextFactory");
>
>        this.context = new InitialContext(properties);
>    }
>
>    @Test
>    public void test1() throws Exception {
>        final Caller roleBean = (Caller)
> this.context.lookup("RoleBeanLocal");
>        roleBean.call(new Callable() {
>
>            @Override
>            public Object call() throws Exception {
>                final MyBean myBean = (MyBean)
> MyBeanTest.this.context.lookup("MyBeanImplLocal");
>                Assert.assertTrue(myBean.doSomething()); // FAILURE
>                return null;
>            }
>        });
>    }
>
>    @Test
>    public void test2() throws Exception {
>        final Caller role2Bean = (Caller)
> this.context.lookup("Role2BeanLocal");
>        role2Bean.call(new Callable() {
>
>            @Override
>            public Object call() throws Exception {
>                final MyBean myBean = (MyBean)
> MyBeanTest.this.context.lookup("MyBeanImplLocal");
>                Assert.assertFalse(myBean.doSomething());
>                return null;
>            }
>        });
>    }
>
>    public static interface Caller {
>
>        <V> V call(Callable<V> callable) throws Exception;
>
>    }
>
>    @Stateless
>    @RunAs("role1")
>    public static class RoleBean implements Caller {
>
>        @Override
>        public <V> V call(final Callable<V> callable) throws Exception {
>            return callable.call();
>        }
>
>    }
>
>    @Stateless
>    @RunAs("role2")
>    public static class Role2Bean implements Caller {
>
>        @Override
>        public <V> V call(final Callable<V> callable) throws Exception {
>            return callable.call();
>        }
>
>    }
> }
>
>
> --
> View this message in context:
> http://openejb.979440.n4.nabble.com/JUnit-Sessioncontext-isCallerInRole-allways-returns-false-tp3257408p3257408.html
> Sent from the OpenEJB User mailing list archive at Nabble.com.
>