【问题标题】:Liquibase & Spring how to use separate user for schema changesLiquibase 和 Spring 如何使用单独的用户进行架构更改
【发布时间】:2014-11-06 08:09:01
【问题描述】:

我正在研究 Liquibase 作为一种潜在的解决方案,可以使用预先存在的数据库服务器(不同类型的)部署我的 Web 应用程序。

此应用程序应该使用只能操作数据的用户访问数据库,我想使用不同的用户作为架构所有者。 由于我的应用程序使用 Spring,我认为我可以使用集成类,但这意味着我必须创建第二个数据源,只要我的应用程序运行,它就会保持打开状态,这违背了分离帐户的目的。

有人遇到过同样的问题吗?任何解决方案的想法?我当然可以手动执行 liquibase 并传递相关信息,但我想知道是否有人想出了更清洁的方法。

提前感谢您的帮助。

【问题讨论】:

    标签: java spring security schema liquibase


    【解决方案1】:

    将 Liquibase 与 Spring Boot(至少 2.0+)一起使用,现在可以在 application.yml 中配置单独的 Liquibase db 用户:

    spring:
      datasource:
        driver-class-name: org.mariadb.jdbc.Driver
        url: jdbc:mariadb://...
        username: <app_user>
        password: ${DB_PASSWORD}
      liquibase:
        default-schema: my_schema
        user: <admin_user>
        password: ${DB_ADMIN_PASSWORD}
    

    【讨论】:

      【解决方案2】:

      感谢您的输入 Nathan,我查看了 Spring 和 CommandLine 类并最终编写了自己的小型静态方法,该方法使用“所有者”凭据打开数据库连接,通过此连接应用更改日志并关闭它。

      然后我从 WebApplicationInitializer 调用此方法,允许 liquibase 在 Spring bean 初始化之前运行。这样,我可以确定在与数据库相关的任何代码运行之前应用更改,而且我只能通过我的数据源进行“用户”连接。

      作为一个很好的副作用,在启动单元测试时也可以使用该静态方法,这使我可以在干净创建的数据库上运行测试,而不是依赖 hibernate 的 DDL。

      这里是代码示例,首先是一个实用程序类,它封装了从我的应用程序的属性文件 (http://pastebin.com/HP4HzFmp) 中检索架构所有者连接详细信息的逻辑,它还有一些方法可以简化与单元测试设置的集成。

      然后在每个 Web 应用程序中,我使用 Spring 的 WebApplicationInitializer,它允许我在应用程序启动时(即在 Hibernate 向 DB 发出任何请求之前)触发 liquibase 更改应用程序:http://pastebin.com/anXicM15。这样做可以让我在架构操作和数据相关连接之间保持完全分离。

      关于数据库连接细节,我将它们全部存储在一个属性文件中,这段代码可以直接读取该文件,并被 Spring 用作 Hibernate 配置的占位符替换源。如果您想实现进一步的隔离,您可以将获取连接细节的部分替换为更安全的位置。

      【讨论】:

      • 我的情况与您的问题完全相同。您能否发布您的解决方案代码或指向 github gist 的链接?这将有很大帮助。
      • 您不需要在您的解决方案中使用 SpringLiquibase 吗?
      • @TechCrunch,我用代码示例编辑了答案,希望对您有所帮助。
      • 非常感谢。我现在继续使用 SpringLiquibase 和第二个数据源,但仍在考虑按照您的方式进行操作。到目前为止,您是否遇到过直接在生产应用程序中升级 DB 的问题?团队中的一些人希望它在应用程序之外手动运行。
      • 到目前为止没有问题,我正在从多个 Web 应用程序运行完全相同的更新,尽管它们都以 Tomcat 的顺序开始。因此,只有第一个实际上应用了任何东西。我还没有测试过同时启动多个节点的情况,尽管在事务中运行更改应该可以确保所有 DBMS 正确处理事务的安全。
      【解决方案3】:

      您是对的,标准的 SpringLiquibase 集成只支持传递一个数据源,并且该数据源将在您的应用程序的整个生命周期中存在。

      如果您使用连接池,一旦 Liquibase 完成它使用的连接,它将被关闭,因此应该没有活动连接,但您的应用程序中仍然会引用它。

      如果你想绕过一个开放的数据源,你可能需要创建一个 SpringLiquibase 的子类来覆盖 afterPropertiesSet() 方法和 getDataSouce() 方法。

      afterPropertiesSet 是运行的主要方法,它创建 Liquibase 实例,然后运行更新方法。如果您的子类创建了一个它想要的新连接,然后调用super.afterPropertiesSet(),然后关闭连接,您应该能够确保一切都被清理干净。在 afterPropertiesSet 中调用 getDataSource() 方法,因此您需要覆盖该方法以返回在 afterPropertiesSet() 中创建的连接。

      你可以在github.com/..../SpringLiquibase.java看到SpringLiquibase是如何实现的

      【讨论】:

        猜你喜欢
        • 2014-05-11
        • 1970-01-01
        • 2017-07-18
        • 1970-01-01
        • 1970-01-01
        • 2021-05-18
        • 1970-01-01
        • 1970-01-01
        • 2018-01-20
        相关资源
        最近更新 更多