在运行时后期更改SessionFactory数据源jdbcurl [英] Change SessionFactory datasource jdbcurl late in runtime

查看:77
本文介绍了在运行时后期更改SessionFactory数据源jdbcurl的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为没有网络连接的环境编写桌面Java应用程序。我试图尽可能安全地将应用程序数据存储在加密的进程内hsqldb中,并使用未加密的用户信息hsqldb。 Hsqldb要求在创建连接时将crypto_key设置在jdbcurl中。我的应用程序使用hibernate做持久性,Spring使用配置和注入。

我现在的方案是将用户名,密码哈希,salt和加密数据库的crypto_key存储在未加密的用户表。 crypto_key通过使用用户密码作为密钥的非对称加密来保护。因此,应用程序不知道应用程序数据的crypto_key是什么,直到它运行了足够长的时间才能加载gui并对用户进行身份验证。



这是我当前的applicationContext.xml。 Spring使用它来让Hibernate正常运转。

 <?xml version =1.0encoding =UTF-8?> 
< beans xmlns =http://www.springframework.org/schema/beans
xmlns:xsi =http://www.w3.org/2001/XMLSchema-instance
xmlns:context =http://www.springframework.org/schema/context
xmlns:tx =http://www.springframework.org/schema/tx
xsi :schemaLocation =http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http:// www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/ tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd\">

< context:component-scan base-package =com.company.domain/>
< context:component-scan base-package =com.company.service/>

< tx:annotation-driven />

< bean id =userDataSource
class =org.springframework.jdbc.datasource.DriverManagerDataSource>
< property name =driverClassNamevalue =org.hsqldb.jdbcDriver/>
< property name =url
value =jdbc:hsqldb:./ ReviewDatabase / users/>
< property name =usernamevalue =reviewer/>
< property name =passwordvalue =$ kelatonKey/>
< / bean>


< bean id =mainDataSource
class =org.springframework.jdbc.datasource.DriverManagerDataSource>
< property name =driverClassNamevalue =org.hsqldb.jdbcDriver/>
< property name =url
value =jdbc:hsqldb:./ ReviewDatabase / data/> <! - TODO:; crypt_key =; crypt_type = AES - >
< property name =usernamevalue =reviewer/>
< property name =passwordvalue =$ kelatonKey/>
< / bean>

< bean id =userSessionFactory
class =org.springframework.orm.hibernate4.LocalSessionFactoryBean>
< property name =dataSourceref =userDataSource/>
< property name =annotatedClasses>
< list>
<值> com.company.domain.AppUser< /值>
< / list>
< / property>
< property name =hibernateProperties>
<道具>
< prop key =hibernate.dialect> org.hibernate.dialect.HSQLDialect< / prop>
< prop key =hibernate.show_sql> true< / prop>
< prop key =hibernate.hbm2ddl.auto> update< / prop>
< /道具>
< / property>
< / bean>

< bean id =mainSessionFactory
class =org.springframework.orm.hibernate4.LocalSessionFactoryBean>
< property name =dataSourceref =mainDataSource/>
< property name =annotatedClasses>
< list>
<! - < value> com.companu.domain.Person< / value> - >
<! - < value> com.company.domain.Thing< /值> - >
<! - < value> com.company.domain.Thing1< /值> - >
<! - <值> com.company.domain.Thing2< /值> - >
<! - <值> com.company.domain.Review< /值> - >
< / list>
< / property>
< property name =hibernateProperties>
<道具>
< pro key =hibernate.dialect> org.hibernate.dialect.HSQLDialect< / prop>
< prop key =hibernate.show_sql> true< / prop>
< prop key =hibernate.hbm2ddl.auto> update< / prop>
< /道具>
< / property>
< / bean>


< bean id =mainTransactionManager
class =org.springframework.orm.hibernate4.HibernateTransactionManager>
< property name =sessionFactoryref =mainSessionFactory/>
< / bean>

< bean id =userTransactionManager
class =org.springframework.orm.hibernate4.HibernateTransactionManager>
< property name =sessionFactoryref =userSessionFactory/>
< / bean>
< / beans>

下面是一个我希望将SessionFactory注入的类的示例

  @Repository(ReviewDao)
公共类HibernateReviewDao实现了ReviewDao {

private SessionFactory mainSessionFactory;

@Autowired
public void setMainSessionFactory(
SessionFactory mainSessionFactory){
this.mainSessionFactory = mainSessionFactory;
}

@Override
@Transactional(value =mainTransactionManager)
public void store(Review Review){
mainSessionFactory.getCurrentSession()。 saveOrUpdate(综述);


$ b @Override
@Transactional(value =mainTransactionManager)
public void delete(Long reviewId){
Review review =(Review)mainSessionFactory.getCurrentSession()
.get(Review.class,reviewId);
mainSessionFactory.getCurrentSession()。delete(review);


$ / code $ / pre
$ b $最后,这是我试过的

 字符串jdbcUrl =jdbc:hsqldb:./ ReviewDatabase / data2; crypt_key = + secret +; crypt_type = AES; 
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySetting(hibernate.dialect,org.hibernate.dialect.HSQLDialect)
.applySetting(hibernate.show_sql,true )
.applySetting(hibernate.hbm2ddl.auto,update)
.applySetting(hibernate.connection.driver_class,org.hsqldb.jdbcDriver)
.applySetting( hibernate.connection.url,jdbcUrl)
.applySetting(hibernate.connection.username,reviewer)
.applySetting(hibernate.connection.password,$ kelatonKey)
.buildServiceRegistry();

SessionFactory mainSessionFactory =新的MetadataSources(serviceRegistry)
.addAnnotatedClass(com.company.domain.Review.class)
.addAnnotatedClass(com.company.domain.Person.class)
.addAnnotatedClass(com.company.domain.Thing.class)
.addAnnotatedClass(com.company.domain.Thing1.class)
.addAnnotatedClass(com.company.domain.Thing2.class )
.buildMetadata()
.buildSessionFactory();
org.springframework.orm.hibernate4.HibernateTransactionManager htm =
(HibernateTransactionManager)context.getBean(mainTransactionManager);
context.getAutowireCapableBeanFactory()。initializeBean(mainSessionFactory,mainSessionFactory);
htm.setSessionFactory(mainSessionFactory);

然而,对此的第一个查询结果是 org .hibernate.HibernateException:找不到当前线程的会话



如何在hibernate初始化之后更改jdbcurl,其他各种各样的汤姆foolery发生了?
我一直在关注这部分的发展,希望谷歌最终能够通过,但我没有想法寻找。所有的答案都会以谦逊的态度接受:)

解决方案

我不知道这是否有帮助,我可以在运行时替换Spring bean定义吗?,你可以虚拟出bean属性开始,然后在运行时更改bean。

I'm writing a desktop java application for an environment without a network connection. I'm trying to store the application data as securely as I can in an encrypted in-process hsqldb, with an unencrypted user information hsqldb. Hsqldb requires that the crypto_key be set in the jdbcurl when the connection is created. My application uses hibernate to do persistence and Spring to do configuration and injection.

My current scheme is to store username, password hash, salt and the encrypted database's crypto_key in the unencrypted user table. The crypto_key is protected by an asymmetric encryption using the user's password as the key. Thus, the application doesn't know what the crypto_key for the application data is until after it has been running long enough to load a gui, and authenticate the user.

Here is my current applicationContext.xml. Spring uses it to get Hibernate going and functioning.

  <?xml version="1.0" encoding="UTF-8"?>
  <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

<context:component-scan base-package="com.company.domain" />
<context:component-scan base-package="com.company.service" />

<tx:annotation-driven />

<bean id="userDataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
    <property name="url" 
        value="jdbc:hsqldb:./ReviewDatabase/users" />
    <property name="username" value="reviewer" />
    <property name="password" value="$kelatonKey" />
</bean>


<bean id="mainDataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
    <property name="url" 
        value="jdbc:hsqldb:./ReviewDatabase/data" /> <!-- TODO: ;crypt_key=;crypt_type=AES -->
    <property name="username" value="reviewer" />
    <property name="password" value="$kelatonKey" />
</bean>

<bean id="userSessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="userDataSource" />
    <property name="annotatedClasses">
        <list>
            <value>com.company.domain.AppUser</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
</bean>

<bean id="mainSessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="mainDataSource" />
    <property name="annotatedClasses">
        <list>
<!--                <value>com.companu.domain.Person</value> -->
<!--                <value>com.company.domain.Thing</value> -->
<!--                <value>com.company.domain.Thing1</value> -->
<!--                <value>com.company.domain.Thing2</value> -->
<!--                <value>com.company.domain.Review</value> -->
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <pro key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
</bean>


<bean id="mainTransactionManager" 
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="mainSessionFactory" />
</bean>

<bean id="userTransactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="userSessionFactory" /> 
</bean>
</beans>

Here's an example of a class where I would like to have the SessionFactory injected

@Repository("ReviewDao")
public class HibernateReviewDao implements ReviewDao{

private SessionFactory mainSessionFactory;

@Autowired
public void setMainSessionFactory(
        SessionFactory mainSessionFactory){
    this.mainSessionFactory = mainSessionFactory;
}

@Override
@Transactional(value = "mainTransactionManager")
public void store(Review review) {
    mainSessionFactory.getCurrentSession().saveOrUpdate(review);

}

@Override
@Transactional(value = "mainTransactionManager")
public void delete(Long reviewId) {
    Review review = (Review)mainSessionFactory.getCurrentSession()
            .get(Review.class, reviewId);
    mainSessionFactory.getCurrentSession().delete(review);
}
}

And finally, here's what I've tried to do after authenticating the user and getting that crypto_key.

String jdbcUrl = "jdbc:hsqldb:./ReviewDatabase/data2;crypt_key=" + secret + ";crypt_type=AES";
    ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
    .applySetting("hibernate.dialect", "org.hibernate.dialect.HSQLDialect")
    .applySetting("hibernate.show_sql", "true")
    .applySetting("hibernate.hbm2ddl.auto","update")
    .applySetting("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver")
    .applySetting("hibernate.connection.url", jdbcUrl)
    .applySetting("hibernate.connection.username", "reviewer")
    .applySetting("hibernate.connection.password", "$kelatonKey")
    .buildServiceRegistry();

    SessionFactory mainSessionFactory = new MetadataSources(serviceRegistry)
        .addAnnotatedClass(com.company.domain.Review.class)
        .addAnnotatedClass(com.company.domain.Person.class)
        .addAnnotatedClass(com.company.domain.Thing.class)
        .addAnnotatedClass(com.company.domain.Thing1.class)
        .addAnnotatedClass(com.company.domain.Thing2.class)
        .buildMetadata()
        .buildSessionFactory();
    org.springframework.orm.hibernate4.HibernateTransactionManager htm = 
            (HibernateTransactionManager)context.getBean("mainTransactionManager");
    context.getAutowireCapableBeanFactory().initializeBean(mainSessionFactory, "mainSessionFactory"); 
    htm.setSessionFactory(mainSessionFactory);  

However, with that, the first query to the object above results in org.hibernate.HibernateException: No Session found for current thread

How can I change the jdbcurl long after hibernate has initialized, dependencies have been injected and other various kinds of tom-foolery has occurred? I've been putting this part of development off, hoping Google would eventually come through, but I'm out of ideas to search for. All answers will be accepted with sheepish humility :)

解决方案

I wonder if this might help, Can I replace a Spring bean definition at runtime? , you could dummy up the bean properties to start with and then change the bean in runtime.

这篇关于在运行时后期更改SessionFactory数据源jdbcurl的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆