Write in front
In some interface request scenarios, the data we want to carry does not want to be submitted in plain text, that is, some obfuscation or encryption processing is required for the parameters, and the backend will decrypt it after obtaining the data to obtain the real data.
The purpose is to protect the security of data and to raise the threshold for being revealed into plain text. For example, in the interface request for user login, if the account and password are transmitted in plain text, it will easily lead to some security problems. At the same time, we do not want anyone to forge parameters to initiate requests on the interface. Therefore, it is very necessary to confuse front-end parameters. Here is a self-use solution, which is the purpose of:
- Prevent information leakage
- Prevent parameters from being tampered with at will
- Improve application security and stability
For the choice of encryption or obfuscation processing methods, e.g.base64
、MD5
Algorithms with low security or irreversibility are not suitable for our scenario, but can be usedAes
andRsa
The combination of the two can realize the encryption and decryption of data.
What interface parameters need to be processed
From a security perspective, it is unanimous here that as long as there are new additions, modifications, and deletion operations on the database, obfuscation/encryption is required. This type of interface is mostlypost
、put
、delete
Wait for a request.
And forget
If the request is a standardized interface, it usually only obtains data and does not have direct operations on the database, so there is no need to do parameter processing.
Of course there ispost
Requests and some file uploads, etc. do not want to be used for parameter processing interfaces, but require special processing, and in the development environment, in order to facilitate debugging, there is no need to be processed.
Parameter processing
becauseRsa
When processing data is large, the advantages are not obvious, and it is suitable for processing scenarios with small data volume, so the processing of parameter data is adoptedAes
Encryption, while participating in encryption keyskey
Then useRsa
Asymmetric encryption improves cracking difficulty.
Related dependencies and version numbers involved:
"crypto-js": "^4.1.1",
"jsencrypt": "^3.2.1"
The solution used here is to first process the original data asquery
String of form, then use it as a random string, participateAes
Encrypt and intercept a specific string as the original key, and perform it againAes
Encryption, and finally use the original key to use the public key agreed with the backendRsa
The specific process and algorithms for encryption processing are as follows:
- Sort and extract parameters
query
String processing - Encrypt and intercept the extracted string using a random string to obtain the key
- Use the key to perform the original parameters
Aes
encryption - Make the key
Rsa
Asymmetric encryption - Output the final
data
andkey
/** * Encrypted request data * @param {Object} rawData * @returns {data, key} */ export function encryptRequestData(rawData) { // Dictionary sorting and assignment var result = {}, str = [], arr = (rawData).sort(); (m => { result[m] = rawData[m] }); // Process it into a query string for (var p in result) (p) && (encodeURIComponent(p) + "=" + encodeURIComponent(result[p])); result = ("&"); // The key participating in Aes encryption will be symmetrically encrypted with 16-bit random codes, and then the 16-bit original key will be obtained from bit 3 const rawKey = aesEncrypt(result, randomString(16)).substr(3, 16); // Output the last encryption parameter const data = aesEncrypt((rawData), rawKey); const key = rsaEncrypt(rawKey); return { data, key } }
Aes Encryption
/** * Aes Encryption * @param {String} data * @param {String} customer_key * @returns encrypted */ export function aesEncrypt(data, customer_key = "") { var key = .(customer_key); var messageHex = .(data); var encrypted = (messageHex, key, { "mode": , "padding": .Pkcs7 }); return (); }
Rsa Encryption
/** * Rsa Encryption */ export function rsaEncrypt(rawData) { let data; try { var rsa = new JsEncrypt(); (publicPem); data = (rawData) } catch (error) { return null } return data; }
Signature verification
If further strengthening tamper protection is needed, a signature can be obtained through a certain algorithm when processing parameters.sign
The value is submitted to the backend together. After the backend is decrypted, the decrypted data is generated by the same algorithm.sign
The value is compared with the submitted one to determine whether it is a legal source of request. I will not give a detailed introduction here.
Processing timing
We need to obfuscate the parameters when requesting interception, here is only forpost
Request and non-local environments. In addition to the development environment, the instance has been added.uncrypt
To identify which interfaces can not participate in processing.
// Request for interception( config => { = "application/x-www-form-urlencoded" const token = ('token') token && ( = token) const { method, uncrypt = false, data = {} } = config; (method === 'post' && !uncrypt && cfg.NODE_ENV === 'development') && ( = encryptRequestData(data)); return config }, error => (error) )
Backend implementation
After the front-end parameters are processed,data
andkey
The objects composed are submitted to the backend, and the service layer accepts them and decrypts them. Here, the implementation is taken as an example. Related dependencies and their version numbers:
"crypto-js": "^4.1.1",
"node-rsa": "^1.1.1"
Rsa decryption
// RSA decryptionrsaDecrypt(data) { let dataObj; return new Promise(function (resolve, reject) { // Store the private key in app/extend/pem/ ('app/extend/pem/', function (err, pem) { const key = new NodeRSA(pem, 'pkcs8-private'); ({ encryptionScheme: 'pkcs1' }); try { dataObj = (data, 'utf8'); } catch (e) { const second = new NodeRSA(pem, 'pkcs8-private'); try { dataObj = (data, 'utf8'); } catch (error) { reject("Rsa decryption failed"); } } resolve(dataObj); }); }); }
Aes decryption
// Aes decryptionaesDecrypt(data, customer_key = "") { var key = .(customer_key || ); var decrypt = (data, key, { "mode": , "padding": .Pkcs7 }); return .(decrypt); }
Handle middleware
Create a new middleware for decryption processingapp/middleware/
= () => { return async function (ctx, next) { const { helper, request } = ctx; const { ajaxMsg } = helper; const { key, data } = ; if (!key || !data) return ajaxMsg(ctx, "-1", "Error request parameter", null, 400); let rawKey; try { rawKey = await (key); } catch (error) { return ajaxMsg(ctx, "-1", "Key resolution failed", null, 400) } if (!rawKey) return ajaxMsg(ctx, "-1", "Key resolution failed", null, 400); const decryptData = ((data, rawKey)); if (!decryptData) return ajaxMsg(ctx, "-1", "Security verification failed", null, 400); = decryptData; await next(); }; };
Used in routing
const { router, controller, middleware } = app; const security = (); // Interface parameter encryption('/common/user/login', security, ); // Log in
The above is the detailed content shared by the JS front-end interface request parameter obfuscation scheme. For more information about JS front-end interface request parameter obfuscation, please pay attention to my other related articles!