5
votes

I'm using embedded Glassfish (org.glassfish.main.extras:glassfish-embedded-all:3.1.2.2) and tried to add a JDBC realm. The application deploys fine but when trying to login (Basic auth. shows the right realm name) the following error message occurs:

com.sun.web.security.RealmAdapter authenticate WARNING: WEB9102: Web Login Failed: com.sun.enterprise.security.auth.login.common.LoginException: Login failed: No LoginModules configured for jdbcRealm

My code looks like this:

embedded Glassfish

// create-jdbc-connection-pool ...    
// create-jdbc-resource ...

String realmProperties = "jaas-context=jdbcRealm:datasource-jndi=jdbc/myDB:user-table=Users:user-name-column=userid:password-column=password:group-table=Groups:group-name-column=groupid;

glassfish.getCommandRunner().run("create-auth-realm", "--classname", "com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm", "--property", realmProperties, myRealm);

web.xml of deployed application

<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>myRealm</realm-name>
</login-config>

I thought if nothing is specified default LoginModule (which in case of a non embedded Glassfish is specified in domain/conf/login.conf) applies?

1

1 Answers

0
votes

The experience I made is that you cant create a security-realm with an embedded glassfish this way. The reason is that you need secure-admin enabled. Of course, you can enable secure-admin in the embedded glassfish but that needs a restart. And thats the point, normally you cant restart the embedded glassfish because you will loose the state so you will loose the configured security-realm too.

The strange thing is I would expect just a failed login, not the missing loginmodules-exception Oo.

The good news, theres another way you could try which maybe helps. If you use EJBContainer.createEJBContainer(props); to create an EJBContainer you can pass some properties and theres one property which we can use. That will look like the following:

Map<String, Object> props = new HashMap<String, Object>();
props.put("org.glassfish.ejb.embedded.glassfish.instance.root", "./src/test/resources/testing-domain");

Now you can specify your entire testing-domain in your test-resources. For that you need to copy some stuff from a working standalone Glassfish 3.1.2.2. I figured out you need the following resources to bring it to work:

testing-domain
    config
        admin-keyfile
        cacerts.jks
        domain.xml (there u can define the security-realm)
        keyfile
        keystore.jks
        logging.properties
        login.conf
        server.policy
        wss-server-config-1.0.xml
        wss-server-config-2.0.xml

If you are using the GlassFishRuntime.bootstrap().newGlassFish(glassfishProperties); you just need the domain.xml and this snippet:

GlassFishProperties glassfishProperties = new GlassFishProperties();
File configFile = new File("src/test/resources/META-INF", "domain.xml");
glassfishProperties.setConfigFileURI(configFile.toURI().toString());

Take care that you change the ports of the server, so u wont get an error if another glassfish-instance is running. Also you should strip the domain.xml for speeding up the tests a bit.

Now you can specify your security-realm in the domain.xml under the tag <security-service> insert something like this:

<auth-realm name="JDBC-AccountRealm" classname="com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm">
    <property name="jaas-context" value="jdbcRealm"></property>
    <property name="password-column" value="PASSWORD"></property>
    <property name="datasource-jndi" value="jdbc/__default"></property>
    <property name="group-table" value="ACCOUNT_GROUP"></property>
    <property name="user-table" value="ACCOUNT"></property>
    <property name="group-name-column" value="GROUPS"></property>
    <property name="group-table-user-name-column" value="EMAIL"></property>
    <property name="user-name-column" value="EMAIL"></property>
    <property name="digest-algorithm" value="SHA-256"></property>
    <property name="encoding" value="Hex"></property>
</auth-realm>

Thats all, easy doing, huh? ;D

Note: You can specify LoginModules in login.conf if you want to.

Note2: I assume that myRealm (without quotes) is a typo in that command? -> 'glassfish.getCommandRunner().run("create-auth-realm", "--classname", "com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm", "--property", realmProperties, myRealm);'