I am developing a server application using Jboss wildfly 8.1 and JPA Hibernate. The problem is, that the JPA datasource creditials have to be loaded at runtime (password). When the server starts, it connects to an encrypted storage where it retrieves password to real database. After that, it should establish connection to the real database.
I tried several things already:
Lookup the datasource through JNDI and rebind it with actual DS.
Lookup the entityManagerFactory through JNDI and rebind it with custom EntityManager.
but none of these work. Do you have idea how to solve it?
my config:
persistence.xml:
org.hibernate.jpa.HibernatePersistenceProvider
java:jboss/datasources/Datasource
...classes...
datasource (defined in standalone.xml):
jdbc:mysql://localhost:3306/repository
false
false
convertToNull
utf8
true
utf8_unicode_ci
mysql
user
TO_BE_DEFINED
accessing entity manager:
@Stateless
@Local
public class GenericDataBean {
@PersistenceContext(type=PersistenceContextType.TRANSACTION)
private EntityManager em;
...
}
解决方案
A possible solution for your problem is use a security domain for the datasource.
In your case you must create custom login module responsible to load password from encrypted storage.
Your configuration should be similar to.
Datasource:
.....
EncryptedPassword
Security Donain:
Login module implementation:
public class EncryptedPasswordLoginModule
extends AbstractPasswordCredentialLoginModule{
private String username;
public void initialize(Subject subject, CallbackHandler handler, Map sharedState, Map options){
super.initialize(subject, handler, sharedState, options);
username = (String) options.get("username");
if( username == null ){
throw new IllegalArgumentException("The user name is a required option");
}
}
public boolean login() throws LoginException{
if( super.login() == true )
return true;
super.loginOk = true;
return true;
}
public boolean commit() throws LoginException{
Principal principal = new SimplePrincipal(username);
SubjectActions.addPrincipals(subject, principal);
sharedState.put("javax.security.auth.login.name", username);
try{
char[] password = .... //code to load encrypted password;
PasswordCredential cred = new PasswordCredential(username, password);
cred.setManagedConnectionFactory(getMcf());
SubjectActions.addCredentials(subject, cred);
}
catch(Exception e){
throw new LoginException("Failed to load encrypted password: "+e.getMessage());
}
return true;
}
public boolean abort(){
username = null;
return true;
}
protected Principal getIdentity(){
Principal principal = new SimplePrincipal(username);
return principal;
}
protected Group[] getRoleSets() throws LoginException{
Group[] empty = new Group[0];
return empty;
}
}
maybe this can help.