V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
godleon
V2EX  ›  程序员

springboot 项目可以动态获取数据库配置吗?

  •  1
     
  •   godleon ·
    aokleon · 214 天前 · 3773 次点击
    这是一个创建于 214 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求

    例 springboot 项目,里面会有 mysql 配置如下:

     spring:
      datasource:
        #数据源基本配置
        username: root
        password: root
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:9999/database_v2
        
    

    想问问怎么能把这个配置在上线的时候隐藏掉?或者动态获取、自己能控制最好

    第 1 条附言  ·  214 天前
    谢谢大家的建议,我统一补充一下

    1.配置中心完全满足,但这是个单体项目,可能里面最多也就不到 10 个接口,如果用配置中心,我还要在项目里加依赖,还要在外部启动注册中心,甚是庞大,目前还是不考虑了

    2.环境变量是是不太满足的,我说一个需求场景吧, 现在我有个 springboot 项目 p1 ,部署到云服务器 c1, 这时候我要在我本地不进入到 c1 服务器的情况下,能修改 p1 的 mysql 数据库配置

    3.我目前为了保证 db 的安全,我部署到云服务器的时候,是挂载的外面的配置文件,然后用启动命令去读配置,然后再删掉,就感觉太麻烦了

    4. #7 楼说的跟我想的差不多,就是用代码配置数据库链接,通过接口调用拿到配置信息,但是这是最没有办法的办法
    ,因为说白了,你用 Http,别人也调你的接口不还是一样吗,最重要的是不能让进到这个服务器的人看到数据库配置
    50 条回复    2023-03-13 09:08:08 +08:00
    smalljop
        1
    smalljop  
       214 天前
    配置中心了解一下 或者从环境变量读取
    wetalk
        2
    wetalk  
       214 天前
    Spring Cloud Consul
    urnoob
        3
    urnoob  
       214 天前
    不放配置文件 放在环境变量里
    theqiang
        4
    theqiang  
       214 天前
    1. “--spring.profiles.active=local”
    2. AbstractRoutingDataSource
    WashFreshFresh
        5
    WashFreshFresh  
       214 天前
    简单点两套配置不好吗
    lsk569937453
        6
    lsk569937453  
       214 天前
    本质上缺一个配置中心。
    yooomu
        7
    yooomu  
       214 天前 via Android
    如果是单体项目,自己创建一个 datasource 放进容器就行了,具体数据可以从环境变量,本地文件,http 请求等等任何途径获取
    bai4246464
        8
    bai4246464  
       214 天前
    nacos ?
    tonyli
        9
    tonyli  
       214 天前
    当然可以,还可以动态添加,动态删减呢
    tonyli
        10
    tonyli  
       214 天前
    前提是你需要确认一个介质你的配置存储在哪里?
    wellerman
        11
    wellerman  
       214 天前
    用携程的 apollo-client 库(可以参考 ruoyi 的老版本),没必要用 nacos ,太重。
    wxw752
        12
    wxw752  
       214 天前
    nacos
    git00ll
        13
    git00ll  
       214 天前
    apollo nacos, 推荐 apollo 写的很好
    litchinn
        14
    litchinn  
       214 天前
    我并没有充分理解你的动态获取配置和隐藏掉是什么意思,但通常这种问题分以下情况:

    1. 只是不想配置在 jar 包里,那可以采取楼上说的配置中心的方式。

    2. 不同环境部署不想每次因为切换数据库就重新打包,那么只需要在 yml 中使用环境变量的方式配置。

    3. 发布时并不知道数据库信息,数据库由用户自己配置,那么可以通过读取配置文件的方式手动创建 DataSource ,当没有配置文件时由用户在页面输入后创建配置文件。

    4. 因为业务需要动态切换不同类型或不同地址数据库,有一些开源的动态数据源的库,例如: https://github.com/baomidou/dynamic-datasource-spring-boot-starter

    如果都不是,那么你应该详细描述你的需求。
    xuanbg
        15
    xuanbg  
       214 天前
    @smalljop 可以动态获取到,但貌似需要重启链接池才能生效。
    godleon
        16
    godleon  
    OP
       214 天前
    @litchinn 说场景吧,现在我有个 springboot 项目 p1 ,部署到云服务器 c1, 这时候我要在我本地不进入到 c1 服务器的情况下,能修改 p1 的 mysql 数据库配置,排除注册中心,因为我一个单体项目,一共不到 10 个接口,我在加依赖,在外部启动注册中心,这就有点太麻烦了
    urnoob
        17
    urnoob  
       214 天前
    oneisall8955
        18
    oneisall8955  
       214 天前
    部署前,获取数据库链接的接口打开,部署后,把接口关了?
    mscorlib
        19
    mscorlib  
       214 天前
    1. 通过 active profile 的方式来指定不同的 profile 文件
    2. 注入 ApplicationContext , 通过 ApplicationContext.getBean(""),来获取不同的 DataSource ;至于 bean name 怎么来,方法有很多:配置文件,环境变量,数据库都可以
    最简单的可控的做法:程序中管理具体用哪个数据源,但是需要一个基础库来存配置
    godleon
        20
    godleon  
    OP
       214 天前
    @oneisall8955 你这个可以实现,这不是就看怎么样更优雅的实现
    mosliu
        21
    mosliu  
       214 天前
    @godleon 从 c1 自己部署一个 api 可以 put 数据库的配置,单独记录到文件中。 然后在连接池初始化的地方,从文件中读取不就行了。。
    mosliu
        22
    mosliu  
       214 天前
    文件做加密。要是说有人再进程序查看加密等的情况,那就没治了。
    litchinn
        23
    litchinn  
       214 天前
    @godleon 根据你的附言第 4 条描述,配置中心也是没用的,服务器别人可以访问,而你不行,那么别人可以拿到 jar 包,即使你使用了配置中心,配置中心的用户密码链接信息不一样写在配置文件吗?配置中心本质和你附言第 4 条说的接口调用方式是一回事。
    那么换个角度,你无法阻止别人拿到信息,那么是否可以从信息加密上做文章呢。
    Jtyczc
        24
    Jtyczc  
       214 天前 via Android
    直接 docker 启动一个 nacos ,很快啊
    leeraya
        25
    leeraya  
       214 天前
    apollo
    godleon
        26
    godleon  
    OP
       214 天前
    @Jtyczc
    1.你得下个 docker
    2.拉个 nacos 镜像
    3.持久化 nacos 配置到 db 或者本地
    4.你需要映射和暴露 nacos 端口,改安全组
    5.你需要项目里加 springcloud-alibaba-nacos 依赖
    VersionGod1
        27
    VersionGod1  
       214 天前
    打 war 包,部署的时候直接改配置类?
    VersionGod1
        28
    VersionGod1  
       214 天前
    看错问题了,不好意思
    jorneyr
        29
    jorneyr  
       214 天前
    SpringBoot 项目里配置 Jasypt 加密一下就好。
    dabai0806
        30
    dabai0806  
       214 天前
    数据库连接信息单独放个数据库表里面
    chrisliu1314
        31
    chrisliu1314  
       214 天前 via Android
    通过 jvm 参数传进去,就不需要配置中心了
    bill110100711
        32
    bill110100711  
       214 天前 via iPhone
    结合七楼的方法,把你的用户名密码加密后用请求传过来,解密用的盐可以放到代码里,代码编译时加混淆。
    godleon
        33
    godleon  
    OP
       214 天前
    @chrisliu1314 目前就是这种方式
    cslive
        34
    cslive  
       214 天前
    jndi 数据源
    zhaokun
        35
    zhaokun  
       214 天前
    你是不让别人看到有数据库连接还是说不想让别人拿到数据库连接账户密码?如果是后者不放铭文不就好了
    lower
        36
    lower  
       214 天前
    感觉你需要的是 数据服务化 ,通过 api 暴露数据的存取,而不是直接数据库暴露;
    搞一套类似 PostgREST 的接口,暴露对数据的操作
    miaotaizi
        37
    miaotaizi  
       214 天前
    springboot 项目用 docker 打包, 读取 docker 容器内的环境变量, 启动 docker 的时候注入变量就行了?
    xiaocaiji111
        38
    xiaocaiji111  
       214 天前
    可以,我们之前项目不允许直连 mysql ,必须请求一个中间服务获取一次性密码初始化 datasource ,配置什么都在这个中间服务。
    具体实现原理估计不难,百度下,很久没看了。
    OldCarMan
        39
    OldCarMan  
       214 天前
    🤔如果换种方式保证你说的“db 安全”,比如动态修改数据库密码,不知道能否满足你的需求,如果满足,加上你的 springboot 项目跟你的 mysql 是部署在同一台服务器的话?你看看可以不可以这样子:

    写个脚本调用 mysql 修改数据库密码的命令,每隔一段时间动态修改一次 mysql 的密码,并把相应密码写入环境变量 /配置文件 /jvm 参数?这样可能可以实现你附言 2 的需求,同时你还可以给该脚本增加手动更新密码的过程,但有点牺牲服务可用性和并且是代码侵入式的,比如你在调用服务接口查数据库时,这时数据库密码改了,服务就会报错,当然你可以采用变量判断的方式,当脚本在修改数据库密码时,给一个变量赋值,然后服务代码里有一个该变量的判断、让接口等待数据返回的过程。

    不过话说回来,你这些“安全需求”,个人觉得都有点“伪需求”的意思,因为凡是影响一件事的因素是多样的时候,就有一个木桶效应,修改数据库配置这种需求,只能增加获取数据库配置的“难度”,但你没法避免别人拿到这些信息,最重要的应该是避免服务器被非信任方使用 /入侵,还有事在人为,很多安全事故都是人祸,管理好服务器使用者也是很有必要的。
    a728976009
        40
    a728976009  
       213 天前
    nilai
        41
    nilai  
       213 天前
    感觉这应该项目应该就是楼主需要把控制权牢牢的把控在自己手中, 应用程序放出去, 但是数据库掌握在自己手中,
    像你之前楼层说的,通过 http 接口返回数据库连接信息,部署完成后把 http 接口关闭。类似的方法很多, 比如把数据库信息隐藏到某个微博中, 或者配合上 aes 、rsa 之类的加解密会更好, 不过你说通过 jvm 参数的话不太靠谱, 你家执行一下 history 命令, 你的数据库信息就暴露出来了
    ZX16815
        42
    ZX16815  
       213 天前
    方案 1 、暴露一个可以修改项目中 datasource 对象的接口,项目启动后,用调接口的形式更新数据。接口参数注意加解密
    方案 2 、用 jasypt 对 yaml 中的数据源基本配置进行加密,注意隐藏好密钥
    kingofzihua
        43
    kingofzihua  
       213 天前
    spring git config ?
    YuanCome
        44
    YuanCome  
       213 天前
    简单操作,本地配置文件然后加密,最后代码解密读取文件就是了
    datoujiejie221
        45
    datoujiejie221  
       213 天前
    加密做的再好,程序还是在别人手中运行,可以通过反编译抓包等方式拿到信息,不如数据库做好权限控制。
    zhaoyta
        46
    zhaoyta  
       213 天前
    jmx 了解下
    mamumu
        47
    mamumu  
       213 天前 via iPhone
    打包时加进去,或者 jvm 参数启动
    Avn
        48
    Avn  
       213 天前
    同意 45 楼的观点。即使通过各种方式隐藏了数据库配置,只要 Spring Boot 应用运行在别人的服务器上,别人还是可以通过 Arthas 等方式,读取到正在运行中的 Spring Boot 应用的很多信息。

    例如,通过以下 Arthas 命令即可获取到连接池 Bean:
    tt -i 1000 -w 'target.getApplicationContext().getBean("dataSource")'
    S1ngleton
        49
    S1ngleton  
       213 天前 via iPhone
    推一个自己之前写的配置中心,是基于 kafka 的订阅推送配置:github.com/Leisurelybear/konfig
    可以 docker 部署试用下看看
    另外还有 java sdk:github Leisurelybear/konfig-sdk-java
    echo1937
        50
    echo1937  
       196 天前
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5297 人在线   最高记录 6067   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 07:43 · PVG 15:43 · LAX 00:43 · JFK 03:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.