one data source with multiple database users
diemon May 19, 2008 5:53 AMHello
I have problem with configuring JBoss 4.2.1+Seam 2.0.1+Oracle 10 to use one data source with multiple users. I have configured *-ds.xml file with
<datasources> <local-tx-datasource> <jndi-name>myDatasource</jndi-name> <connection-url>jdbc:oracle:thin:@server:1521:db</connection-url> <driver-class>oracle.jdbc.driver.OracleDriver</driver-class> <security-domain>MyRealm</security-domain> </local-tx-datasource> </datasources>
and added to login-config.xml:
<authentication> <login-module code = "my.login.module.MyLoginModule" flag = "required"> <module-option name="sysUserName">user</module-option> <module-option name="sysPassword">pass</module-option> <module-option name="managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=myDatasource</module-option> </login-module> </authentication>
my login module code is as follows:
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.acl.Group;
import java.util.Map;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.resource.spi.ManagedConnectionFactory;
import javax.resource.spi.security.PasswordCredential;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import org.jboss.mx.util.MBeanServerLocator;
import org.jboss.seam.security.Identity;
import org.jboss.security.SecurityAssociation;
import org.jboss.security.SimplePrincipal;
import org.jboss.security.auth.spi.AbstractServerLoginModule;
public class MyLoginModule extends AbstractServerLoginModule {
 private static final org.apache.log4j.Logger log = org.apache.log4j.Logger
 .getLogger(my.login.module.MyLoginModule.class);
 /* used at jboss startup */
 private static boolean sysMode = true;
 private String sysUserName;
 private String sysPassword;
 private String userName;
 private String password;
 private MBeanServer server;
 private ObjectName managedConnectionFactoryName;
 private ManagedConnectionFactory mcf;
 public SkorLoginModule() {}
 @Override
 public void initialize(Subject subject, CallbackHandler handler, Map sharedState, Map options) {
 super.initialize(subject, callbackHandler, sharedState, options);
 String name = (String) options.get("managedConnectionFactoryName");
 try {
 managedConnectionFactoryName = new ObjectName(name);
 } catch (MalformedObjectNameException mone) {
 throw new IllegalArgumentException("Malformed ObjectName: " + name);
 }
 sysUserName = (String)options.get("sysUserName");
 if (sysUserName == null) {
 throw new IllegalArgumentException("Must supply a system user name!");
 }
 userName = (String)options.get("sysUserName");
 sysPassword = (String)options.get("sysPassword");
 if (sysPassword == null) {
 throw new IllegalArgumentException("Must supply a system user password!");
 }
 password = (String)options.get("sysPassword");
 server = MBeanServerLocator.locateJBoss();
 getMcf();
 }
 @Override
 public boolean login() throws LoginException {
 setUserNameAndPassword();
 log.info("login(): userName=" + userName + ", sysMode=" + sysMode);
 Principal principal = new SimplePrincipal(userName);
 PasswordCredential credential = new
 PasswordCredential(userName, password.toCharArray());
 credential.setManagedConnectionFactory(getMcf());
 subject.getPrincipals().add(principal);
 subject.getPrivateCredentials().add(credential);
 super.loginOk = true;
 return true;
 }
 protected ManagedConnectionFactory getMcf() {
 if (mcf == null) {
 try {
 mcf = (ManagedConnectionFactory)server.getAttribute(managedConnectionFactoryName, "ManagedConnectionFactory");
 } catch (Exception e) {
 throw new IllegalArgumentException("Managed Connection Factory not found: " + managedConnectionFactoryName);
 }
 }
 return mcf;
 }
 @Override
 protected Principal getIdentity() {
 setUserNameAndPassword();
 log.info("getIdentity(): userName=" + userName + ", sysMode=" + sysMode);
 return new SimplePrincipal(userName);
 }
 @Override
 protected Group[] getRoleSets() throws LoginException {
 return new Group[] {};
 }
 private void setUserNameAndPassword() {
 if (sysMode) {
 userName = sysUserName;
 password = sysPassword;
 } else {
 String[] ss = Identity.instance().getUsername().split(" ");
 String s = ss[0].substring(0, 1).toLowerCase();
 s += ss[1].toLowerCase();
 userName = s;
 password = s;
 }
 }
}
The problem is that when I try to switch user with:
org.jboss.seam.security.Identity.instance().setUsername("User Name");
SkorLoginModule.setSysMode(false);
try {
 LoginContext loginContext = new LoginContext("MyRealm");
 loginContext.login();
} catch (LoginException e) {
 System.out.println("error");
}
there aren't created any sub-pools for every user. There is one physical db connection. When I try to flush cache from JaasSecurityManager, the connection i reseted and previously logged in user is disconnected.
Another question is: when should I invoke
loginContext.login()because now it's invoked in a stateless bean which authenticate method is configured in seam's compoments.xml file as:
<security:identity authenticate-method="#{authenticator.authenticate}"
 security-rules="#{securityRules}"/>
I think the authenticate method should be invoked somewhere else - in authenticator bean the entity manager is already injected by @PersistenceContext annotation.
Thanks in advance for any help.
 
     
     
    