Первый взгляд на типичный файл конфигурации
... 省略 ...
## 配置MySQL数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://121.196.xxx.xxx:3306/user?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
## 配置Redis缓存连接
redis.host=121.196.xxx.xxx
redis.port=6379
redis.password=111111
## 配置SMS短信服务连接
ali.sms.access_key_id=2zHmLdxAes7Bbe2w
ali.sms.access_key_secret=bImWdv6iy0him8ly
... 省略 ...
Это выдержка из типичного проекта Spring Boot.application.properties
конфигурационный файл.
тсс...Скажите по секрету, многие друзья тоже так пишут?
Это нормально на первый взгляд, и многие люди берут это как должное. Включая себя, я видел много проектов (включая многие проекты с открытым исходным кодом), написанные так.
Но после тщательного рассмотрения я обнаружил, что:
Да!В конфигурационных файлах многих проектов, в том числе пароли к БД, кешированные пароли или ключи каких-то сторонних сервисов настраиваются прямо в нем, без всякого шифрования!
Некоторые люди скажут, что этот файл конфигурации все равно принадлежит мне, каков риск?
Ну я уже видел пример.Программист загрузил код проекта своей компании в собственный репозиторий GitHub.В результате конфигурационный файл забыл обработать,что привело к утечке базы данных компании.Ключевая проблема в том,что эта компания еще гостиница.Управляйте компанией,так что последствия можно себе представить...
С другой точки зрения, если бы вся важная информация в конфигурационном файле этого проекта была зашифрована в то время, то этой сцены, вероятно, не произошло бы. Таким образом, даже файл конфигурации проекта, важная информация должна быть зашифрована!
Какая информация должна быть зашифрована?
Вообще говоря, в конфигурационном файле проекта должны быть обработаны все конфигурационные элементы (или поля), относящиеся к информационной безопасности, такие как:
- Используемые базы данных, кешированные пароли
- Используемое промежуточное ПО, пароль очереди сообщений
- Access_Key различных используемых сторонних сервисов
- Сообщения от других сторонних сервисов
- ......и т.д
Все вообще, ключевые поля должны быть защищены, по крайней мере, не непосредственно записаны в простом тексте в файле конфигурации!
Как зашифровать элементы конфигурации?
Метод очень прост и может быть выполнен за несколько шагов.Давайте сначала продемонстрируем минимальную версию:
1. Сначала создайте базовый проект Spring Boot
Это больше не
2. Представьтеjasypt-spring-boot
Криптографические компоненты
пройти черезjasypt-spring-boot
Этот готовый компонент шифрования поставляетсяJasypt
Эта мощная криптографическая библиотека
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
3. Настройте ключ шифрования
Файл конфигурации проекта в Spring Bootapplication.properties
Добавьте следующую конфигурацию:
jasypt.encryptor.password=CodeSheep
Может понятьjasypt
Этот пользовательский ключ шифрования будет использоваться для шифрования важных элементов в файле конфигурации.
4. Проверка шифрования
Чтобы облегчить тестирование, мы напрямую расширяем класс запуска проекта Spring Boot, выполняем зашифрованный тестовый код при запуске проекта и непосредственно видим эффект.
@SpringBootApplication
public class SpringBootConfigEncryptApplication implements CommandLineRunner {
@Autowired
private ApplicationContext appCtx;
@Autowired
private StringEncryptor codeSheepEncryptorBean;
public static void main(String[] args) {
SpringApplication.run(SpringBootConfigEncryptApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
Environment environment = appCtx.getBean(Environment.class);
// 首先获取配置文件里的原始明文信息
String mysqlOriginPswd = environment.getProperty("spring.datasource.password");
String redisOriginPswd = environment.getProperty("redis.password");
String aliSmsOriginAk = environment.getProperty("ali.sms.access_key_secret");
// 加密
String mysqlEncryptedPswd = encrypt( mysqlOriginPswd );
String redisEncryptedPswd = encrypt( redisOriginPswd );
String aliSmsEncryptedAk = encrypt( aliSmsOriginAk );
// 打印加密前后的结果对比
System.out.println( "MySQL原始明文密码为:" + mysqlOriginPswd );
System.out.println( "Redis原始明文密码为:" + redisOriginPswd );
System.out.println( "阿里云SMS原始AccessKey密码为:" + aliSmsOriginAk );
System.out.println( "====================================" );
System.out.println( "MySQL原始明文密码加密后的结果为:" + mysqlEncryptedPswd );
System.out.println( "Redis原始明文密码加密后的结果为:" + redisEncryptedPswd );
System.out.println( "阿里云SMS原始AccessKey密码加密后的结果为:" + aliSmsEncryptedAk );
}
private String encrypt( String originPassord ) {
String encryptStr = codeSheepEncryptorBean.encrypt( originPassord );
return encryptStr;
}
private String decrypt( String encryptedPassword ) {
String decryptStr = codeSheepEncryptorBean.decrypt( encryptedPassword );
return decryptStr;
}
}
Запустив проект, консоль выводит:
MySQL原始明文密码为:123456
Redis原始明文密码为:111111
阿里云SMS原始AccessKey密码为:bImWdv13da894mly
====================================
MySQL原始明文密码加密后的结果为:IV7SyeQOfG4GhiXeGLboVgOLPDO+dJMDoOdmEOQp3KyVjruI+dKKeehsTriWPKbo
Redis原始明文密码加密后的结果为:litUkxJ3fN6+//Emq3vZ+y4o7ZOnZ8doOy7NrgJIDLoNWGG0m3ygGeQh/dEroKvv
阿里云SMS原始AccessKey密码加密后的结果为:MAhrOs20DY0RU/c1IKyLCt6dWZqLLOO4wUcK9GBgSxNII3C+y+SRptors+FyNz55xNDslhDnpWllhcYPwZsO5A==
5. Измените файл конфигурации и замените элементы конфигурации, которые необходимо зашифровать.
Получаем результат шифрования, полученный на предыдущем шаге, и заменяем исходный текстовый пароль в конфигурационном файле на результат, соответствующий предыдущему шагу, вот так:
Поэтому рекомендуется обрабатывать всю важную информацию в конфигурационном файле таким образом!
6. Просмотрите результат расшифровки пароля
@SpringBootApplication
public class SpringBootConfigEncryptApplication implements CommandLineRunner {
@Autowired
private ApplicationContext appCtx;
@Autowired
private StringEncryptor codeSheepEncryptorBean;
public static void main(String[] args) {
SpringApplication.run(SpringBootConfigEncryptApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
Environment environment = appCtx.getBean(Environment.class);
// 首先获取配置文件里的配置项
String mysqlOriginPswd = environment.getProperty("spring.datasource.password");
String redisOriginPswd = environment.getProperty("redis.password");
String aliSmsOriginAk = environment.getProperty("ali.sms.access_key_secret");
// 打印解密后的结果
System.out.println( "MySQL原始明文密码为:" + mysqlOriginPswd );
System.out.println( "Redis原始明文密码为:" + redisOriginPswd );
System.out.println( "阿里云SMS原始AccessKey密码为:" + aliSmsOriginAk );
}
}
распечатать результат:
MySQL原始明文密码为:123456
Redis原始明文密码为:111111
阿里云SMS原始AccessKey密码为:bImWdv13da894mly
Очевидно, что при использовании в кодеjasypt-spring-boot
компонент будет автоматическиENC()
Зашифрованные поля элементов конфигурации, завернутые в синтаксис, автоматически расшифровываются, и данные можно восстановить.
Дети, у вас много вопросительных знаков?
На этот раз я уверен, что многие мелкие партнеры выразили сомнения, типичный пример:
1. Ключ шифрования должен быть помещен вENC()
середина? ЗачемENC
?
2. Хотя исходные элементы конфигурации, связанные с информационной безопасностью, зашифрованы, индивидуальный ключ шифрованияjasypt.encryptor.password=CodeSheep
Если он просочился, есть ли шанс, что другие смогут его расшифровать?
Чтобы ответить на эти вопросы, продолжайте читать.
Пользовательский префикс и суффикс шифрования
Если вы не хотите использоватьjasypt
предоставляется по умолчаниюENC
Чтобы пометить зашифрованное поле, его можно заменить настраиваемым знаком префикса и суффикса, например, я хочу заменить его наCodeSheep()
Чтобы отметить зашифрованное поле, вам нужно только настроить префикс и суффикс в файле конфигурации:
jasypt.encryptor.property.prefix=CodeSheep(
jasypt.encryptor.property.suffix=)
В это время зашифрованное поле можно поместить вCodeSheep()
Поле тега:
Сделайте шифрование более безопасным
Хотя после вышеуказанного шифрования элементы конфигурации, связанные с информационной безопасностью, однозначно станут более безопасными, в этом можно не сомневаться!
Но если пользовательский ключ шифрования в файле конфигурацииjasypt.encryptor.password=CodeSheep
В случае утечки наши зашифрованные поля все еще могут быть расшифрованы другими, поэтому существует несколько работ, направленных на то, чтобы сделать шифрование более безопасным.
1. Используйте собственный шифратор
При экспериментировании с шифрованием выше мы использовалиПравила шифрования по умолчанию, что делает его потенциально небезопасным при утечке пользовательских ключей шифрования. Для этого мы можем настроить правила шифрования.
Пользовательские правила шифрования очень просты, просто нужно предоставитьПользовательский класс конфигурации шифратораВот и все, например, я настраиваю файл с именемcodeSheepEncryptorBean
Тип шифратора:
@Configuration
public class CodeSheepEncryptorCfg {
@Bean( name = "codeSheepEncryptorBean" )
public StringEncryptor codesheepStringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword("CodeSheep");
config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
config.setKeyObtentionIterations("1000");
config.setPoolSize("1");
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
return encryptor;
}
}
УведомлениездесьBean
названиеname
необходимо указать явно (имя по умолчаниюjasyptStringEncryptor
), если вы используете пользовательское имя, как здесь, вам также необходимо использовать Spring Bootapplication.properties
файл конфигурации для указанияbean
имя, например:
jasypt.encryptor.bean=codeSheepEncryptorBean
2. Не записывайте ключ шифрования в конфигурационный файл
Если вы чувствуете, что вышеуказанный способ все же может привести к утечке ключа шифрования (ведь он все равно прописан в конфигурационном файле), то мы можем просто удалить шифровальный ключ из конфигурационного файла и заменить его натри пути:
- метод первый: Непосредственно при запуске программыаргументы командной строкиввести
java -jar yourproject.jar --jasypt.encryptor.password=CodeSheep
- Способ 2: Непосредственно при запуске программыПеременные среды приложенияввести
java -Djasypt.encryptor.password=CodeSheep -jar yourproject.jar
- способ третий: может даже использоваться каксистемные переменные окруженияспособ ввести
Например, заранее устанавливаем системные переменные окруженияJASYPT_ENCRYPTOR_PASSWORD = CodeSheep
, вы можете выполнить следующую настройку непосредственно в файле конфигурации проекта Spring Boot:
jasypt.encryptor.password=${JASYPT_ENCRYPTOR_PASSWORD:}
Тогда будет намного безопаснее.
тсс...
Ладно, так много сказано, если важная информация в конфигурационном файле вашего проекта не зашифрована, обещайте мне, больше ничего не говори, быстро и тайно все это изменить, быстро! скорость! Беги вперед!