前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 中如何加密配置文件中的数据库账号和密码?

Java 中如何加密配置文件中的数据库账号和密码?

作者头像
Java极客技术
发布2022-12-04 10:25:37
2.4K0
发布2022-12-04 10:25:37
举报
文章被收录于专栏:Java极客技术

作为程序员每天的开发工作都离不开跟数据库打交道,而且我们的应用程序往往都会配置数据库的链接,那你有没有想过,任何一个能接触到我们项目代码的人员,都可以看到配置文件里面的账号秘密?

相信很多人的项目里面配置文件都是类似这样写的

代码语言:javascript
复制
############### Mysql配置 #########################
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/abc?useUnicode=true&characterEncoding=utf-8&useTimezone=true&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456

spring.datasource.url 中配置了数据库的链接地址和端口,spring.datasource.username 配置了账号以及spring.datasource.password 中配置了密码。

如果是这样的写法,无非就是在裸奔,任何一个能接触到这个文件的人,都能够用 MySQL 的客户端工具进行数据库的链接,里面的数据毫无安全可言。当然如果是本地或者测试环境都还可以,但是对于生产环境那是不能接受的,毕竟这样的安全性太差了,一不小心被删库跑路还是有可能的。

相对而言,有一些经验的数据库运维人员是不会直接提供数据库服务的 IP 地址和端口的,而是提供域名,通过在 url 地址上面配置相应的域名,然后通过解析域名让其访问数据库服务,域名地址是不对外解析的,所以生产环境的主机以及开发人员的本机,需要进行 hosts 的配置,将域名对应 IP 地址配置起来。

这种方式会比上面直接裸奔的形式好一点,外人拿到代码,没有 hosts 配置也是不能访问数据库的,难度相对来说高了一点。但是这样也有个问题,那就是开发人员还是可以通过 MySQL 的客户端进行数据的访问,如果哪天心情不好,删库跑路也不是没有可能,或者说私自泄露数据也是有机会的。

那么很多小明就问了,有没有一种方式,可以有效的控制这种情况呢?让尽量少了人接触到数据库的数据,但是同时也不能影响开发的进度,对于开发要友好。

有问题,就会有答案,这个时候我们就需要介绍一款神器了,那就是 jasyptjasypt 可以帮助我们在配置文件中配置加密后的账号和密码,然后结合秘钥,就可以完全控制数据库的安全性。下面我们就来试一下吧。

首先有一个需要连接数据库的 Spring Boot 服务,我们先看一下,在没有引入 jasypt 的时候,是如何使用的,代码如下:

代码语言:javascript
复制
############### Mysql配置 #########################
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/abc?useUnicode=true&characterEncoding=utf-8&useTimezone=true&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456

#客户端等待连接池连接的最大毫秒数
spring.datasource.hikari.connection-timeout=20000
#最小空闲连接数
spring.datasource.hikari.minimum-idle=5
#最大连接池大小
spring.datasource.hikari.maximum-pool-size=20
#连接池中空闲的最长时间毫秒
spring.datasource.hikari.idle-timeout=30000
#池中连接关闭后的最长生命周期毫秒
spring.datasource.hikari.max-lifetime=1200000
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.connection-test-query=SELECT 1

UserController.java

代码语言:javascript
复制
package com.controller;

import com.mapper.UserEntity;
import com.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.List;

@RestController
@EnableAutoConfiguration
@RequestMapping("/user")
public class UserController {

  @Autowired
  private UserMapper userMapper;

  @RequestMapping("add")
  public int addUser(String name, String desc) throws Exception {
    int id, num = 0;
    UserEntity u = new UserEntity(0, name, desc, new Date());
    num = userMapper.insert(u);
    id = u.getId();
    return id;
  }

  @RequestMapping("getlist")
  public List<UserEntity> listUser() throws Exception {
    List<UserEntity> UserEntitys = userMapper.getAll();
    System.out.println(UserEntitys.toString());
    return UserEntitys;
  }
}

UserMapper.java

代码语言:javascript
复制
package com.mapper;

import org.apache.ibatis.annotations.*;

import java.util.List;

/**
 * @author ziyou
 */
public interface UserMapper {
  /**
   * 查询操作示例
   *
   * @return
   */
  @Select("SELECT * FROM t_user;")
  @Results({
    @Result(property = "id", column = "Id"),
    @Result(property = "Name", column = "Name"),
    @Result(property = "Desc", column = "Desc"),
    @Result(property = "CreateTime", column = "CreateTime")
  })
  List<UserEntity> getAll();

  /**
   * 插入操作示例
   * 将自增ID绑定到实体,keyProperty是实体字段,keyColumn是数据库字段
   *
   * @param user
   * @return
   */
  @Insert("INSERT INTO t_user(`Name`,`Desc`,CreateTime) VALUES(#{Name}, #{Desc}, #{CreateTime});")
  @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "Id")
  int insert(UserEntity user);

}

另外我们有一张表,表里面的数据是这样的,接下来我们启动服务,调用接口查询表的数据,如下所示

说明在使用明文账号密码的时候,整个流程是没有问题,接下来,我们引入 jasypt ,主要分下面三个步骤

引入 pom 依赖

代码语言:javascript
复制
<!--springboot整合jasypt-->
    <dependency>
      <groupId>com.github.ulisesbocchio</groupId>
      <artifactId>jasypt-spring-boot-starter</artifactId>
      <version>1.18</version>
    </dependency>

编写加密工具类

代码语言:javascript
复制
public class JasyptUtil {

  public static void main(String[] args) {
    String account = "root";
    String password = "123456";
    BasicTextEncryptor encryptor = new BasicTextEncryptor();
    //秘钥
    //encryptor.setPassword(System.getProperty("jasypt.encryptor.password"));
    encryptor.setPassword("eug83f3gG");
    //密码进行加密
    String newAccount = encryptor.encrypt(account);
    String newPassword = encryptor.encrypt(password);
    System.out.println("加密后账号:" + newAccount);
    System.out.println("加密后密码:" + newPassword);
  }
}

因为我们要得到加密后的密文,所以我们先需要根据原始账号密码,以及我们指定的秘钥来生成加密后的密文,这里我们假设本地和测试环境的秘钥为eug83f3gG,通过上面的工具类,我们可以生成如下的密文

替换账号密码,我们将 application.properties 里面的账号密码用上面的密文替换,如下所示,使用 ENC()包住密文。

代码语言:javascript
复制
############### Mysql配置 #########################
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/abc?useUnicode=true&characterEncoding=utf-8&useTimezone=true&serverTimezone=GMT%2B8
spring.datasource.username=ENC(/YnTvPH7WnnqMHu+wKeccA==)
spring.datasource.password=ENC(Xv829RzVs7pd2sv72/wsbg==)

这里说明三点

  1. 此时我们还不能正常启动服务,因为就这样的话是启动不成功了,账号和密码是错误的,我们需要将秘钥传入,让jasypt 给我们反向解析出正确的账号和密码才能进行数据库的链接;
  2. 工具类中的秘钥保持跟生产环境不一样!!!
  3. 使用 ENC() 包住密文;

接下来我们可以将秘钥通过两种形式传进程序中使用,一种是将秘钥通过系统环境变量的形式进行配置,不过不建议;第二种是通过启动参数将秘钥进行传入;这里我们使用第二种,在 SpringBoot 项目的启动参数中,我们增加这样的配置 -Djasypt.encryptor.password=eug83f3gG,然后我们再重启应用,就可以启动成功了。

启动成功了再次访问上面的接口,可以看到效果是一样的。

后续在生产环境中,只需要在启动参数中传入与本地和测试环境不一样的秘钥,就可以有效的防止数据库的账号密码被泄露了,就连开发人员都不知道是什么,只要配置的运维人员知道,这个安全性就高很多了,怎么样小伙伴你学会了吗?赶紧在自己的项目中用起来吧!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-02-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java极客技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
访问管理
访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档