Передний
предыдущий постРука об руку научит вас аутентификации при входе в апплетПредставляет, как апплет выполняет аутентификацию при входе в систему, затем идентификатор пользователя общего апплета может использовать идентификатор, предоставленный WeChat, упомянутый выше.jscode2session
В обмен на интерфейс апплет также предоставляетgetUserInfo
API для получения пользовательских данных, эти пользовательские данные также могут содержать текущий идентификатор пользователя openid. Эта статья оКак получить пользовательские данные и честь целостности данных в апплетеи т. д., чтобы расширить детали
Введение в API
wx.getUserInfo
Это интерфейс API, используемый для получения информации о пользователе. Ниже приведены соответствующие поля параметров:
поле | Типы | Требуется ли |
---|---|---|
withCredentials | Boolean | нет |
lang | String | нет |
timeout | Number | нет |
success | Function | нет |
fail | Function | нет |
complete | Function | нет |
lang
lang указывает язык, на котором возвращается пользовательская информация, с тремя значениями:
- zh_CN Упрощенный китайский
- zh_TW Традиционный китайский
- en Английский, по умолчанию en
timeout
timeout указывает время ожидания для вызова API,getUserInfo
По сути, нижний уровень API заключается в том, что клиент инициирует http-запрос для получения соответствующих данных пользователя и возвращает их апплету после инкапсуляции, которая будет подробно представлена позже.
withCredentials
withCredentials Это поле является логическим значением, которое определяет, включается ли информация о статусе входа в данные, возвращаемые апплетом при вызове API.Если оно не заполнено, значением по умолчанию для этого поля являетсяtrue
Тогда результат, возвращаемый API в это время:
поле | Типы | описывать |
---|---|---|
encryptedData | String | зашифрованные данные пользователя |
iv | String | Вектор алгоритма расшифровки |
rawData | String | Открытые данные пользователя |
signature | String | подписать |
userInfo | Object | Открытые данные пользователя |
Если значение этого поляfalse
, указанные выше два поля не будут возвращены:encryptedData
, iv
.
-
зашифрованные данные — это зашифрованные данные полной информации о пользователе, включая конфиденциальные данные. Конфиденциальные данные включают
openid
а такжеunionid
Ждать. Тогда алгоритм, используемый для шифрования данных,AES-128-CBC
Блочный симметричный алгоритм шифрования и дешифрования, этот алгоритм шифрования мы подробно разберем позже. -
iv — начальный вектор алгоритма описанного выше алгоритма дешифрования. Также мы представим его подробно позже.
-
rawData — объектная строка, содержащая некоторые открытые данные пользователя, а именно:
nickName(微信昵称)
,province(所属省份)
,language(微信客户端内设置的语言类型)
,gender(用户性别)
,country(所在国家)
,city(所在城市)
,avatarUrl(微信头像地址)
-
подпись Чтобы гарантировать достоверность и безопасность данных, апплет подписывает данные открытого текста. Это значение
sha1(rawData + session_key)
расчетное значение,sha1
Это криптографическая хеш-функция, по сравнению сmd5
Хеш-функции более устойчивы к атакам. -
Поле userInfo представляет собой объект и данные, открытые пользователем, которые соответствуют содержимому, отображаемому rawData, за исключением того, что rawData сериализует объект в строку в качестве возвращаемого значения.
HTTP-запрос API
Я говорил вам ранее о вызове клиентаgetUserInfo
Когда используется API, клиент WeChat отправит запрос на сервер WeChat.В инструменте разработчика WeChat вы можете увидеть через захват пакета HTTP-запроса, что запрос был отправлен.https://servicewechat.com/wxa-dev-logic/jsoperatewxdata
такой http запрос.
тело запросаОн содержит несколько важных параметров, в том числеdata
, grant_type
и т. д., поле данных представляет собой строку JSON с полем в нейapi_name
, значение которого — «webapi_userinfo». Поле grant_type также соответствует значению «webapi_userinfo».
тело ответавозвращает объект JSON, сначалаbaseresponse
поле, содержащее код возврата вызова интерфейсаerrcode
и результат вызоваerrmsg
. Объект также возвращаетdata
поле, это поле данных соответствует строке JSON, которая содержит всю информацию о пользовательских данных, полученную при вызове API. В инструментах разработчика мы также видим, чтоdebug_info
поле, которое также содержит данные пользователяdata
, но здесьdata
Также возвращается openid пользователя и учетные данные пользователя для входа в систему session_key.
Как правило, мы можем отлаживать достоверность некоторой информации, включая данные пользователя.session_key
а такжеopenid
.
Алгоритм шифрования AES-128-CBC
Как мы сказали выше, полная информация о пользователе, полученная через API в апплетеencryptedData
, надо пройтиAES-128-CBC
алгоритм шифрования и дешифрования. Сначала разберемся, что такоеAES-128-CBC
:
Полное имя AES является расширенным стандартом шифрования. Это спецификация шифрования для электронных данных, установленных Национальным институтом стандартов и технологий (NIST) в 2001 году. Это стандарт шифрования блока. Каждый размер блока шифрования составляет 128 бит. Длина 128, 192 и 256 бит.
Существует пять режимов блочного шифрования, а именно
Режим кодовой книги ECB (Electronic Codebook Book)
CBC (Cipher Block Chaining) Режим цепочки шифровальных блоков
Режим калькулятора CTR (счетчик)
CFB (Cipher FeedBack) Режим обратной связи по шифру
OFB (Output FeedBack) Режим обратной связи на выходе
Здесь мы в основном рассматриваемAES-128-CBC
Алгоритм блочного шифрования заключается в использовании одного и того же набора ключей для преобразования открытого текста и зашифрованного текста, где 128 бит — это группа, 128 бит — это 16 байт, а затем каждые 16 байтов открытого текста в виде группы соответствуют зашифрованному 16-байтовому паролю. Если последнего оставшегося открытого текста не хватает на 16 байт, его необходимо заполнить, обычно используяPKCS#7
(PKCS#5 поддерживает заполнение только 8-байтовых блоков данных, тогда как PKCS#7 поддерживает байтовые блоки от 1 до 255) для заполнения.
Если последний оставшийся открытый текст составляет 13 байт, то есть 3 байта отсутствуют для формирования группы, то в это время необходимо заполнить 3 байта 0x03:
明文数据: 05 05 05 05 05 05 05 05 05 05 05 05 05
PKCS#7填充: 05 05 05 05 05 05 05 05 05 05 05 05 05 03 03 03
Если открытый текст представляет собой целое число, кратное 16 байтам, в конце для шифрования следует добавить 16-байтовую группу 0x10.
Таким образом, мы находим две характеристики заполнения PKCS#7:
-
Байты заполнения - это один и тот же байт
-
Значение этого байта — количество байтов, которые необходимо заполнить.
Давайте еще раз посмотрим на процесс шифрования открытого текста. В режиме CBC каждый зашифрованный блок подвергается операции XOR с зашифрованным текстом предыдущего зашифрованного блока перед шифрованием, а затем результат будет зашифрован шифровальщиком. такой же, как тот, который мы описали ранееiv初始化向量
Блок данных подвергается операции XOR. Как показано ниже (картинка из википедии):
Но нужно четко указать, что этот API возвращаетiv
является вектором инициализации, соответствующим алгоритму расшифровки, а не вектором инициализации, соответствующим алгоритму шифрования. Таким образом, вы, должно быть, догадались, что первый блок шифра также необходимо подвергнуть операции XOR с вектором инициализации при расшифровке в режиме CBC. Как показано ниже (картинка из википедии):
В апплете зашифрованные и расшифрованные шифры — это шифры в кодировке base64, полученные в нашей предыдущей статье.session_key
.
Приложения в мини-программах
Затем, когда у нас есть общее представление о том, как пользовательские данные шифруются в апплете, давайте возьмем в качестве примера nodejs, чтобы увидеть, как расшифровать пользовательские данные на стороне сервера и проверить целостность расшифрованных данных:
В файле util.js определены два метода:
decryptByAES
Метод заключается в использовании сервера, предоставленного WeChat, при входе в систему.jscode2session
получено из интерфейсаsession_key
и что будет возвращено после вызова wx.getUserInfoiv
вектор инициализации для расшифровкиencryptedData
.
encryptedBySha1
метод черезsha1
хеш-алгоритм для шифрованияsession_keyСгенерируйте идентификатор статуса входа пользователя самого приложения апплета, чтобы убедиться, чтоsession_keyбезопасность.
// util.js
const crypto = require('crypto');
module.exports = {
decryptByAES: function (encrypted, key, iv) {
encrypted = new Buffer(encrypted, 'base64');
key = new Buffer(key, 'base64');
iv = new Buffer(iv, 'base64');
const decipher = crypto.createDecipheriv('aes-128-cbc', key, iv)
let decrypted = decipher.update(encrypted, 'base64', 'utf8')
decrypted += decipher.final('utf8');
return decrypted
},
encryptBySha1: function (data) {
return crypto.createHash('sha1').update(data, 'utf8').digest('hex')
}
};
В файле auth.js вызывается метод из предыдущей статьиgetSessionKey
метод получения пользователемopenid
а такжеsession_key
После получения как зашифрованных данных является расшифрованная рабочая операция пользователя, в то время как пользовательские данные и дешифрованные пользователем Session_key Skey и сохраненные таблицы данных.
Здесь следует отметить одну вещь: если текущий апплет привязан к мобильному приложению или веб-приложению открытой платформы, официальной учетной записи публичной платформы и т. д., тоencryptedData
вернет еще одинunionId
поле, этот unionId может различать уникальность пользователей между мини-программами и другими связанными платформами, то естьУ одного и того же пользователя один и тот же unionid для разных приложений на одной и той же открытой платформе WeChat.. Как правило, мы можем использовать unionId для получения состояния входа пользователя между апплетом и другими приложениями.
// auth.js
const { decryptByAES, encryptBySha1 } = require('../util');
return getSessionKey(code, appid, secret)
.then(resData => {
// 选择加密算法生成自己的登录态标识
const { session_key } = resData;
const skey = encryptBySha1(session_key);
let decryptedData = JSON.parse(decryptByAES(encryptedData, session_key, iv));
// 存入用户数据表中
return saveUserInfo({
userInfo: decryptedData,
session_key,
skey
})
})
.catch(err => {
return {
result: -10003,
errmsg: JSON.stringify(err)
}
})
Проверка целостности и достоверности данных
После того, как мы получим полные данные пользователя посредством расшифровки, мы можем проверить целостность и достоверность полученных данных, чтобы предотвратить злонамеренное изменение данных пользователя. Вот как выполнить проверку связанных данных:
Проверка действительности: Ранее мы говорили, что когдаwithCredentials
Если установлено значение true, возвращаемые данные также будут включатьsignature
поле, значение которогоsha1(rawData + session_key)
В результате разработчик может использовать тот же алгоритм sha1 для вычисления соответствующей подписи2 на стороне сервера полученной подписи, то есть
signature2 = encryptedBySha1(rawData + session_key);
Целостность пользовательских данных определяется путем сравнения соответствия подписи и подписи2.
Проверка целостности: Попасть передencryptedData
И после соответствующей операции расшифровки вы увидите, что в объекте объекта пользовательских данных есть объектwatermark
Поле, официально называемое водяным знаком данных, структура этого поля такова:
"watermark": {
"appid":"APPID",
"timestamp":TIMESTAMP
}
Здесь разработчики могут проверить, соответствует ли appid в водяном знаке их собственному appid, а также отметке времени, полученной из данных в водяном знаке, чтобы проверить своевременность данных.
наконец
Итак, вышеизложенное является введением в то, как шифровать и расшифровывать пользовательские данные в апплете, а также как обрабатывать и проверять пользовательские данные.Пожалуйста, посоветуйте!
Справочная статья:
Подробное объяснение криптографических алгоритмов — AES
Пять режимов шифрования AES (CBC, ECB, CTR, OCF, CFB)
Некоторое понимание алгоритма шифрования AES-128-CBC
Режимы работы Advanced Encryption Standard AES (ECB, CBC, CFB, OFB)
Технологический еженедельник IVWEBШок в сети, обратите внимание на публичный номер: сообщество IVWEB, регулярно каждую неделю публикуйте качественные статьи.