好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

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

############### 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 %  2 B8
spring .datasource  .username  = root
spring .datasource  .password  =  123456 

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

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

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

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

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

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

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

############### 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 %  2 B8
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
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
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 ,主要分下面三个步骤

1.引入 pom 依赖

  springboot整合jasypt -->   < dependency >   < groupId > com .github  .ulisesbocchio   groupId >   < artifactId > jasypt - spring - boot - starter  artifactId >   < version >  1.18   version >    dependency >     

2.编写加密工具类

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,通过上面的工具类,我们可以生成如下的密文

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

############### 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 %  2 B8
spring .datasource  .username  = ENC (  / YnTvPH7WnnqMHu + wKeccA ==  )  spring .datasource  .password  = ENC ( Xv829RzVs7pd2sv72 / wsbg ==  ) 

这里说明三点

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

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

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

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

原文地址:https://mp.weixin.qq测试数据/s/gGO9tIbCaP9HEfny0tgwTg

查看更多关于Java 中如何加密配置文件中的数据库账号和密码?的详细内容...

  阅读:38次