我正在使用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;
...
}
答案 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)