目標
1:禁止網(wǎng)站分析。
2:保證Cookies安全挂绰。
3:http請求數(shù)據(jù)安全抛腕。
4:http請求防重堤尾。
方案
1:禁止網(wǎng)站分析
- 禁止右鍵審查元素和開啟F12
使用disable-devtool庫:https://github.com/theajack/disable-devtool
- 如果開啟了F12肝劲,那么出發(fā)debug干擾審查元素
// 循環(huán)監(jiān)測,當(dāng)檢測到開啟了Dev那么開啟deg模式
setInterval(function () {
check();
}, 4000);
var check = function () {
function doCheck(a) {
if (("" + a / a)["length"] !== 1 || a % 20 === 0) {
(function () { }["constructor"]("debugger")());
} else {
(function () { }["constructor"]("debugger")());
}
doCheck(++a);
}
try {
doCheck(0);
} catch (err) { }
};
check();
2:保證Cookies安全
- 使用AES將保存的內(nèi)容加密:基于crypto-js
import CryptoJS from "crypto-js";
const keyCode = "223434ae2f1123a234cb"
export default {
en(word, keyStr = keyCode) {
let enc = CryptoJS.AES.encrypt(word, CryptoJS.enc.Hex.parse(keyStr), {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
})
return enc.ciphertext.toString()
},
de(word, keyStr = keyCode) {
let dec = CryptoJS.AES.decrypt(CryptoJS.format.Hex.parse(word), CryptoJS.enc.Hex.parse(keyStr), {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
})
return CryptoJS.enc.Utf8.stringify(dec)
}
};
3:http請求數(shù)據(jù)安全哀峻。
- 將請求體加密涡相,密鑰要和服務(wù)器端匹配
import CryptoJS from "crypto-js";
const keyCode = "223434ae2f1123a234cb"
export default {
en(word, keyStr = keyCode) {
let enc = CryptoJS.AES.encrypt(word, CryptoJS.enc.Hex.parse(keyStr), {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
})
return enc.ciphertext.toString()
},
de(word, keyStr = keyCode) {
let dec = CryptoJS.AES.decrypt(CryptoJS.format.Hex.parse(word), CryptoJS.enc.Hex.parse(keyStr), {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
})
return CryptoJS.enc.Utf8.stringify(dec)
}
};
- 在攔截器中統(tǒng)一加密
// request interceptor
service.interceptors.request.use(
config => {
config.data = encry.en(JSON.stringify(config.data))
return config
},
error => {
Promise.reject(error)
}
)
- java后臺對應(yīng)加密
package com.cloudcc.microservice.devconsolesvc.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
@Slf4j
public class AESUtil {
/**
* 加密算法:AES
*/
private static String Algorithm = "AES";
/**
* 算法/模式/補碼方式
*/
private static String AlgorithmProvider = "AES/ECB/PKCS5Padding";
/**
* 默認密鑰:
*/
private static String defaultKey = "devconsole-svc12";
/**
* @param src 明文
* @param key 密鑰
* @return
* @version 1.0
* @description 加密
* @date 2021/7/26 19:52
*/
public static String encrypt(String src, String key) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
if (StringUtils.isEmpty(key)) {
key = defaultKey;
}
SecretKey secretKey = new SecretKeySpec(key.getBytes("utf-8"), Algorithm);
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] cipherBytes = cipher.doFinal(src.getBytes(Charset.forName("utf-8")));
return byteToHexString(cipherBytes);
}
/**
* @param src 密文
* @param key 密鑰
* @return
* @version 1.0
* @description 解密
* @date 2021/7/26 19:57
*/
public static String decrypt(String src, String key) throws Exception {
if (StringUtils.isEmpty(key)) {
key = defaultKey;
}
SecretKey secretKey = new SecretKeySpec(key.getBytes("utf-8"), Algorithm);
Cipher cipher = Cipher.getInstance(AlgorithmProvider);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] hexBytes = hexStringToBytes(src);
byte[] plainBytes = cipher.doFinal(hexBytes);
return new String(plainBytes, "utf-8");
}
/**
* 將byte轉(zhuǎn)換為16進制字符串
*
* @param src
* @return
*/
public static String byteToHexString(byte[] src) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xff;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
sb.append("0");
}
sb.append(hv);
}
return sb.toString();
}
/**
* 將16進制字符串裝換為byte數(shù)組
*
* @param hexString
* @return
*/
public static byte[] hexStringToBytes(String hexString) {
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] b = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
b[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return b;
}
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
public static void main(String[] args) {
try {
// java中密鑰必須是16的倍數(shù)
String key = "comconsbck-moc21";
String src = "{\n" +
" \"head\":{},\n" +
" \"body\":{\n" +
" \n" +
" \"pageApi\":\"test-a\"\n" +
" }\n" +
"}";
System.out.println("vue中的密鑰:" + byteToHexString(key.getBytes()));
System.out.println("原字符串:" + src);
String enc = encrypt(src, key);
System.out.println("加密:" + enc);
System.out.println("解密:" + decrypt("de1132750d63a572333933c9b5ed545f", key));
} catch (Exception e) {
e.printStackTrace();
}
}
}
4:http請求防重。
- 請求體中添加時間戳剩蟀,服務(wù)器端獲取和服務(wù)器事件對比催蝗,時間差小于5分鐘,為有效請求育特。
- 請求體中添加隨機字符串丙号,服務(wù)器將隨機字符串放入Map中,如果請求的隨機串存在Map中缰冤,那么視為無效請求犬缨。