Wildfly - 在运行时设置数据源密码

时间:2014-10-20 12:15:13

标签: java-ee jpa jboss datasource wildfly-8

我正在使用Jboss wildfly 8.1和JPA Hibernate开发服务器应用程序。问题是,必须在运行时加载JPA数据源信用(密码)。当服务器启动时,它连接到加密存储,在那里它检索真实数据库的密码。之后,它应该建立与真实数据库的连接。

我已经尝试了几件事: 通过JNDI查找数据源并使用实际DS重新绑定它。 通过JNDI查找entityManagerFactory并使用自定义EntityManager重新绑定它。

但这些都不起作用。你知道如何解决它吗?

我的配置:

的persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0">
   <persistence-unit name="PERSISTENCE_UNIT" transaction-type="JTA">
      <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

      <jta-data-source>java:jboss/datasources/Datasource</jta-data-source>
      ...classes...

      <properties>
        <!-- Properties for Hibernate -->               
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
        <property name="hibernate.hbm2ddl.auto" value="update"/>
        <property name="hibernate.show_sql" value="false"/>
        <property name="hibernate.format_sql" value="false"></property>
        <property name="hibernate.connection.useUnicode" value="true"/>
        <property name="hibernate.connection.characterEncoding" value="UTF-8"/>
        <property name="hibernate.connection.charSet" value="UTF-8"/>
        <property name="org.hibernate.flushMode" value="commit" /> <!-- THIS ONE IS IMPORTANT -->

        <property name="jboss.entity.manager.factory.jndi.name" value="java:/EntityManagerFactory"/>
        <property name="jboss.entity.manager.jndi.name" value="java:/Manager1"/>
      </properties>      
   </persistence-unit>
</persistence>

datasource(在standalone.xml中定义):

            <datasource jndi-name="java:jboss/datasources/Datasource" pool-name="DS" enabled="true" use-java-context="true">
                <connection-url>jdbc:mysql://localhost:3306/repository</connection-url>
                <connection-property name="useCompression">
                    false
                </connection-property>
                <connection-property name="logSlowQueries">
                    false
                </connection-property>
                <connection-property name="zeroDateTimeBehavior">
                    convertToNull
                </connection-property>
                <connection-property name="characterEncoding">
                    utf8
                </connection-property>
                <connection-property name="useUnicode">
                    true
                </connection-property>
                <connection-property name="connectionCollation">
                    utf8_unicode_ci
                </connection-property>
                <driver>mysql</driver>
                <security>
                    <user-name>user</user-name>
                    <password>TO_BE_DEFINED</password>
                </security>
            </datasource>

访问实体经理:

@Stateless
@Local
public class GenericDataBean {

    @PersistenceContext(type=PersistenceContextType.TRANSACTION)
    private EntityManager em;

...
}

3 个答案:

答案 0 :(得分:1)

问题的可能解决方案是security domain使用datasource。 在您的情况下,您必须创建负责从加密存储加载密码的custom login module 您的配置应类似于。

<强>数据源:

<datasource ... >
   .....
   <security>
          <security-domain>EncryptedPassword</security-domain>
   </security>
</datasource>

安全Donain:

<security-domain name="EncryptedPassword">
    <authentication>
        <login-module code="com.example.EncryptedPasswordLoginModule" flag="required">
            <!-- list of options -->
            <module-option name="username" value="theusername"/>
            <module-option name="managedConnectionFactoryName" value="jboss.jca:service=LocalTxCM,name=DS"/>
        </login-module>
    </authentication>
</security-domain>

登录模块实施:

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;
   }
}

也许这会有所帮助。

答案 1 :(得分:0)

您如何访问SubjectActions类?类访问修饰符是默认的,因此它在编译时抛出错误错误:class EncryptedPasswordLoginModule是public,应该在名为EncryptedPasswordLoginModule.java的文件中声明

答案 2 :(得分:0)

@javaguy这是我的完整课程,希望对您有帮助

scala> import scala.util._ 
import scala.util._

scala> val x: Try[String] = Success[String]("abc")
x: scala.util.Try[String] = Success(abc)

scala> val y: Try[String] = Failure[String](new Exception("oops"))
y: scala.util.Try[String] = Failure(java.lang.Exception: oops)

scala> val z = Try(x)
z: scala.util.Try[scala.util.Try[String]] = Success(Success(abc))

scala> val t = Try(y)
t: scala.util.Try[scala.util.Try[String]] = Success(Failure(java.lang.Exception: oops))

scala> z.flatten
res2: scala.util.Try[String] = Success(abc)

scala> t.flatten
res3: scala.util.Try[String] = 
Failure(java.lang.UnsupportedOperationException: oops)