Как обеспечить безопасность данных при взаимодействии интерфейсного и внутреннего API?

задняя часть внешний интерфейс Spring JavaScript

предисловие

Метод разработки внешнего и внутреннего разделения, мы используем интерфейс в качестве стандарта для продвижения, определения интерфейса, разработки собственных функций и, наконец, внесения совместных корректировок. Независимо от того, разрабатываете ли вы собственное приложение, веб-приложение или программное обеспечение для ПК, до тех пор, пока интерфейс и серверная часть разделены, интерфейс, предоставляемый серверной частью, неизбежно будет использоваться для делового взаимодействия.

Для веб-страниц или приложений, пока вы получаете пакет, вы можете четко знать данные, полученные по этому запросу.Такой интерфейс является благом для инженеров-краулеров, и ваши данные легко собирать.

Безопасность данных очень важна, особенно информация, относящаяся к пользователям, которая может быть незаконно присвоена преступниками, если они не будут осторожны.

Как обеспечить безопасность данных во время вызовов API?

  1. Для связи используется https
  2. Подпись запроса для предотвращения подделки параметров
  3. Механизм подтверждения личности, каждый запрос должен быть проверен на законность
  4. Используйте закрепление ssl в приложении, чтобы предотвратить захват пакетов
  5. Шифровать и расшифровывать все запросы и ответы
  6. Ждите план....

Шифровать и расшифровывать все запросы и ответы

Схем много.Чем больше вы делаете, тем выше безопасность.Сегодня я познакомлю вас со схемой шифрования и расшифровки всех запросов и ответов.Даже если вы можете перехватывать пакеты,даже если вы можете называть меня интерфейсом,но данные, которые я возвращаю, зашифрованы. Пока алгоритм шифрования достаточно надежен, это не повлияет на меня, если вы получите мой зашифрованный контент.

Такую работу лучше всего выполнять единым образом. Нельзя позволить каждому разработчику обратить внимание на этот вопрос. Если вы позволите каждому разработчику обратить внимание на этот вопрос, это будет очень хлопотно, и вам придется data при возврате метода data., после получения данных необходимо вызвать метод расшифровки.

С этой целью я инкапсулировал Starter на основе Spring Boot со встроенным алгоритмом шифрования AES. Адрес GitHub выглядит следующим образом:

GitHub.com/Йинджи Хуан/Да…

Давайте сначала посмотрим, как его использовать.Вы можете загрузить исходный код, затем импортировать его, а затем добавить аннотацию @EnableEncrypt в класс запуска, чтобы включить операции шифрования и дешифрования:

@EnableEncrypt
@SpringBootApplication
public class App {
	
    public static void main(String[] args) {
		SpringApplication.run(App.class, args);
    }
}

Добавьте конфигурацию зашифрованного ключа:

spring.encrypt.key=abcdef0123456789
spring.encrypt.debug=false
  • spring.encrypt.key: ключ шифрования, должен быть 16 бит.
  • spring.encrypt.debug: включить ли режим отладки, по умолчанию — false, если true, операции шифрования и дешифрования не включены.

Чтобы считаться универсальным, он не выполняет шифрование и дешифрование для всех запросов, делает контроль на основе аннотаций.

Если данные ответа необходимо зашифровать, просто добавьте аннотацию @Encrypt к методу контроллера.

@Encrypt
@GetMapping("/list")
public Response queryNews(String city) {
	return Response.ok(city);
}

Когда мы обращаемся к интерфейсу /list, возвращаемые данные представляют собой формат с кодировкой base64 после шифрования.

Другая операция — это данные, представленные в предыдущем разделе, которые разделены на два случая.Один — запрос на получение, который пока не обработан и будет рассмотрен позже.В настоящее время обрабатывается только запрос на отправку на основе метод отправки в формате json, то есть фон. Вам нужно использовать @RequestBody для получения данных, и мы можем добавить аннотацию @Decrypt к операции, которую необходимо расшифровать.

@Decrypt
@PostMapping("/save")
public Response savePageLog(@RequestBody PageLogParam logParam, HttpServletRequest request) {
	pageLogService.save(logParam);
	return Response.ok();
}

После добавления аннотации @Decrypt данные, отправленные внешним интерфейсом, должны быть зашифрованы в соответствии с алгоритмом шифрования AES, а затем отправлены на серверную часть, которая автоматически расшифрует их, а затем сопоставит с объект параметров.

Приведенные выше пояснения относятся ко всему внутреннему коду. Если используется внешний интерфейс, мы объясним его на js. Конечно, вы также можете сделать это на других языках. Если это нативное приложение для Android, оно также обрабатывается в java-коде.

Передняя часть должна делать 2 вещи:

  1. Ответ данных обрабатывается единообразно, а операция расшифровки выполняется до рендеринга на страницу
  2. Когда отправляются данные POST-запроса, унифицированное шифрование

js, см. aes.js, crypto-js.js, pad-zeropadding.js в шифровании на моем GitHub

Мы используем axios в качестве основы для запроса данных и используем перехватчик axios для единообразной обработки операций шифрования и дешифрования.

Прежде всего, нам еще нужно инкапсулировать js-класс шифрования и дешифрования.Следует отметить, что зашифрованный ключ должен быть в паре с фоновым, иначе они не могут расшифровать друг друга.Код выглядит следующим образом:

var key  = CryptoJS.enc.Latin1.parse('abcdef0123456789');
var iv   = CryptoJS.enc.Latin1.parse('abcdef0123456789');

// 加密
function EncryptData(data) {
	var srcs = CryptoJS.enc.Utf8.parse(data);
	var encrypted = CryptoJS.AES.encrypt(srcs, key, {
		mode : CryptoJS.mode.ECB,
		padding : CryptoJS.pad.Pkcs7
	});
	return encrypted.toString();
}

// 解密
function DecryptData(data) {
	var stime = new Date().getTime();
	var decrypt = CryptoJS.AES.decrypt(data, key, {
		mode : CryptoJS.mode.ECB,
		padding : CryptoJS.pad.Pkcs7
	});
	var result = JSON.parse(CryptoJS.enc.Utf8.stringify(decrypt).toString());
	var etime = new Date().getTime();
	console.log("DecryptData Time:" + (etime - stime));
	return result;
}

Унифицированный код обработки в перехватчике axios:

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
	// 对所有POST请加密,必须是json数据提交,不支持表单
	if (config.method == "post") {
		config.data = EncryptData(JSON.stringify(config.data));
	}
    return config;
  }, function (error) {
    return Promise.reject(error);
});

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
	// 后端返回字符串表示需要解密操作
	if(typeof(response.data) == "string"){
		response.data = DecryptData(response.data);
	}
    return response;
  }, function (error) {
	return Promise.reject(error);
});

До сих пор мы выполняли операцию шифрования для всей связи между интерфейсом и сервером.Пока зашифрованный ключ не просочился, другим бесполезно получить ваши данные.Вопрос в том, как убедиться, что ключ не слил?

Защищенность сервера высокая, можно хранить в базе данных или в конфигурационном файле.Ведь на нашем собственном сервере самое опасное это собственно фронтенд.Приложение нормальное и его можно запаковать, но проблемы такие поскольку декомпиляция должна быть предотвращена.

Если это веб-приложение, его можно реализовать, полагаясь на шифрование js.Ниже я представлю способ динамического получения ключа шифрования, но его сложнее реализовать.

Алгоритмы шифрования включают симметричное шифрование и асимметричное шифрование, AES — симметричное шифрование, а RSA — асимметричное шифрование. Причина, по которой AES используется для шифрования данных, заключается в том, что он эффективен, а RSA работает медленно и может использоваться для операций подписи.

Мы можем использовать эти два алгоритма, чтобы дополнять друг друга для обеспечения безопасности, использовать RSA для шифрования и передачи секретного ключа AES и использовать AES для шифрования данных, Эти два алгоритма сочетаются друг с другом и имеют дополнительные преимущества.

На самом деле, если вы понимаете принцип HTTPS, вы должны с первого взгляда понять следующее содержание: Причина, по которой HTTPS медленнее, чем HTTP, заключается в том, что клиент и сервер должны безопасно согласовать алгоритм симметричного шифрования. Остальное заключается в том, что обе стороны используют этот симметричный алгоритм шифрования для шифрования и дешифрования во время общения.

  1. Клиент запускается, отправляет запрос на сервер, и сервер использует алгоритм RSA для генерации пары открытого ключа и закрытого ключа, которую мы называем pubkey1, prikey1 для краткости, и возвращает открытый ключ pubkey1 клиенту.
  2. После того, как клиент получает открытый ключ pubkey1, возвращенный сервером, он использует алгоритм RSA для генерации пары открытого ключа и закрытого ключа, которую мы называем pubkey2, prikey2 для краткости, и шифрует открытый ключ pubkey2 с помощью открытого ключа pubkey1, и передает его на сервер после шифрования.
  3. В это время сервер получает зашифрованный текст, переданный клиентом, и расшифровывает его закрытым ключом prikey1, поскольку данные зашифрованы открытым ключом pubkey1, а открытый ключ pubkey2, сгенерированный клиентом, может быть получен путем расшифровки.
  4. Затем мы генерируем симметричное шифрование, то есть наш AES, который на самом деле является ключом шифрования с длиной 16 относительно того, что в нашей конфигурации.После генерации этого ключа мы шифруем его с помощью открытого ключа pubkey2 и возвращаем его в клиент, потому что только у клиента есть закрытый ключ prikey2, соответствующий pubkey2, и только клиент может его расшифровать.После того, как клиент получает данные, он использует prikey2 для их расшифровки для получения ключа шифрования AES.Наконец, используется зашифрованный ключ зашифровать передачу данных, и весь процесс заканчивается.

принцип spring-boot-starter-encrypt

Наконец, давайте кратко представим принцип spring-boot-starter-encrypt, и пусть все поймут, почему Spring Boot так удобен, а многих функций можно добиться с помощью простой настройки.

Аннотация @EnableEncrypt в классе запуска используется для включения функции, а класс автоматической конфигурации импортируется через @Import.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({EncryptAutoConfiguration.class})
public @interface EnableEncrypt {

}

Классы обработки для настройки запросов и ответов в EncryptAutoConfiguration используют RequestBodyAdvice и ResponseBodyAdvice в Spring, в Spring удобнее выполнять статистическую обработку запросов. Если вы хотите инкапсулировать на более низком уровне, вам придется иметь дело с этим из сервлета.

@Configuration
@Component
@EnableAutoConfiguration
@EnableConfigurationProperties(EncryptProperties.class)
public class EncryptAutoConfiguration {

	/**
	 * 配置请求解密
	 * @return
	 */
	@Bean
	public EncryptResponseBodyAdvice encryptResponseBodyAdvice() {
		return new EncryptResponseBodyAdvice();
	}
	
	/**
	 * 配置请求加密
	 * @return
	 */
	@Bean
	public EncryptRequestBodyAdvice encryptRequestBodyAdvice() {
		return new EncryptRequestBodyAdvice();
	}
	
}

Ответ на запрос можно обработать через RequestBodyAdvice и ResponseBodyAdvice, и общий принцип таков.

Для большего обмена технологиями, пожалуйста, обратите внимание на общедоступную учетную запись WeChat: Yuantiandi

image.png