引
網站cookie中有一段用戶信息(包括微信用戶信息,用戶關聯信息)的文本,使用entrance
鍵存儲,選擇不同的條件後文本內容也不同,cookie上的值也會變化。本來的打算是通過將entrance
值存儲在sessionstorage,然後通過比較當前請求中cookie的值與sessionstorage的值是否一致來得出用戶是否選擇了其他條件從而進行其他操作。
但是不想將entrance
鍵的值直接存儲到sessionstorage中,一來該值內容較長,基本上超過1000個字符,二來只是爲了進行比較操作就存儲原始的用戶信息做法不是很友好。
所以想要一個簡單的文本摘要算法,以達到上述訴求。在網絡上搜索了一番,並沒有一個零依賴,簡單的文本摘要算法。只好自己理了下思路寫出了一個簡單的文本摘要算法。分享出來,以饗讀者。
正
/**
* 簡單的文本摘要算法。
* ! 不要用於敏感業務
* @param {String} text 待摘要的文本,必需
* @param {String} salt 加鹽內容
* @param {Number} caesar 凱撒字符偏移長度
* @param {Object} opts 其他配置項
* @property {Number} opts.blockLength 分塊長度
*/
export default function textSummary(
text = "",
salt = "[簡單]文本摘要算法",
caesar = 5,
opts = {}
) {
if (typeof text !== "string") {
throw new Error("entrance value must be a string");
}
const { blockLength = 16 } = opts;
if (blockLength >= 36 || blockLength < 16) {
throw new Error(
"blockLength options prop is wrong value, it is value in range:16~36"
);
}
// 加鹽
const textArr = `${text};salt=${salt}`.split("");
const _0bTextArr = textArr
.map(str => str.codePointAt(0) + caesar) // 凱撒字符偏移
.map(num => num.toString(2)); // 轉化爲二進制
// 分塊
const _0bTextStr = _0bTextArr.join("");
const blockAmount = Math.ceil(_0bTextStr.length / blockLength);
const _0bTextBlockArr = Array(blockAmount);
for (let i = 0; i < blockAmount; i++) {
let subStr = _0bTextStr.slice(i * blockLength, (i + 1) * blockLength);
// 最後一塊字符長度不足,補0
if (subStr.length !== blockLength) {
subStr = subStr.padEnd(blockLength, "0");
}
_0bTextBlockArr[i] = subStr;
}
// 將二進制塊轉化爲16進制塊
const _0xTextBlockArr = _0bTextBlockArr.map(str =>
parseInt(str, 2).toString(blockLength)
);
const result = _0xTextBlockArr.join("");
return result;
}
釋
算法設計思路是:
- 對原始文本進行加鹽處理。
- 獲取到處理後文本的Unicode字符碼點位置,並將獲取到的位置進行凱撒字符偏移處理。
- 將偏移後的位置(爲十進制的結果)轉化爲二進制。
- 對整個二進制文本按指定的塊長度進行分塊處理。最後一塊內容如果字符長度不足,則補0。
- 將分好的每個塊的二進制內容轉爲十六進制內容。
- 將得到的每個塊的十六進制內容拼接在一起並返回其值。
思考了下,由於在步驟4對最後一塊內容進行了補0操作,導致該塊內容在逆處理時得不到肯定的值,從而導致算法不可逆。
本算法雖說是摘要算法,但實質上有加密,線性壓縮的一點功能。但還好已經滿足了原本的要求。