声明:只是因为工作中需要,且基本不会对别人的网站构成什么不好的影响,做个思路记录!!!
尊重网站所有者、控制请求频率、遵守网站规则、尊重个人隐私
平常工作中难免会遇到需要爬取别人网站的需求,例如爬取兑换之类的流程,把接口爬取下来封装到项目中,这种一般不会对别人的网站有什么的影响,因为也是正常流程下单,例如下面的活动截图:
AES+RSA:使用RSA秘钥生成工具生成一对公钥(A)和私钥(B),前端保留A,后端保留B。
前端发送数据时,先生成一串随机16位字符串作为AES的秘钥(C),然后使用A使用RSA算法对C进行加密,得到加密后的AES秘钥(D)。将要发送的数据(E)用C使用AES加密,得到密文(F)。将D和F一同发给后端进行处理。
后端处理数据时,先用B对D使用RSA进行解密得到C,用C对F使用AES进行解密得到E,处理后得到结果G,再用C对G进行AES加密得到H,将H返回给前端。
前端接收到H后用C进行解密,得到处理的结果G。
根据AES和RSA的配合流程来看,这里没有直接返回RSA公钥,而是根据摸和指数来生成RSA公钥然后加密AES私钥,用AES私钥去加密数据进行传输,但是从前面请求参数来看,跟我们平常看到的AES和RSA字符串不一样,显然还做了相关的转换,dataKey字段只有数字和小写字母,平常看到的加密数据还有大写字母、+、/等。
public static void main(String[] args) {
// 创建JavaScript引擎
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
try {
// 加载JavaScript文件
engine.eval(new FileReader("C:\\Users\\win\\Desktop\\index2.js"));
// 执行JavaScript函数
Object result = engine.eval("Fp()");
// 这里是我习惯用serr打印测试日志,因为标红比较显眼
System.err.println("Function Result: " + JSONObject.toJSONString(result));
// 拿到Fp()函数返回的dataKey等数据
JSONObject object = JSONObject.parseObject(JSONObject.toJSONString(result));
// 要加密的数据
String content = "{\"appId\":\"xxxx\"}";
System.err.println("加密前的数据:" + content);
// 加密后的数据
String encryptAES = encryptAES(content, object.getString("key"), object.getString("iv"));
System.err.println("加密后的数据:" + encryptAES);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* AES加密
* @param plaintext 要加密的数据
* @param key
* @param iv
*/
public static String encryptAES(String plaintext, String key, String iv) {
try {
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
return bytesToHex(encryptedBytes).toUpperCase();
} catch (Exception e) {
log.error("AES加密异常,{}", e.getMessage());
return "";
}
}
private static String bytesToHex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02X", b));
}
return result.toString();
}
/**
* 获取浏览器驱动
*/
private WebDriver getDriver(Param pm) {
// 设置随机的设备 user-agent 和屏幕大小
Map<String, Object> mobileEmulation = new HashMap<>();
Map<String, Object> map = new HashMap<>();
Dimension randomScreenSize = getRandomScreenSize();
map.put("width", randomScreenSize.getWidth());
map.put("height", randomScreenSize.getHeight());
mobileEmulation.put("deviceMetrics", map);
if (pm != null && Func.isNotBlank(pm.getUserAgent())) {
// 设置UA
mobileEmulation.put("userAgent", pm.getUserAgent());
}
//谷歌浏览器设置
ChromeOptions options = new ChromeOptions();
// 隐藏浏览器、无头浏览器
options.addArguments("-headless");
options.setExperimentalOption("mobileEmulation", mobileEmulation);
// 打开F12
// options.addArguments("--auto-open-devtools-for-tabs");
// 启动无沙盒模式运行,以最高权限运行
options.addArguments("--no-sandbox");
// 不加载图片, 提升速度
options.addArguments("blink-settings=imagesEnabled=false");
options.addArguments("--disable-dev-shm-usage");
// 禁用gpu渲染
options.addArguments("--disable-gpu");
// 禁用阻止弹出窗口
options.addArguments("--disable-popup-blocking");
// 禁用扩展
options.addArguments("disable-extensions");
// 禁用默认浏览器检查
options.addArguments("no-default-browser-check");
// 忽略不信任证书
options.addArguments("–ignore-certificate-errors");
// 禁用自动化控制特性
options.addArguments("--disable-blink-features=AutomationControlled");
// 禁用通知
options.addArguments("--disable-notifications");
// 禁用信息栏
options.addArguments("--disable-infobars");
// 禁用日志记录
options.addArguments("--disable-logging");
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
options.setCapability("goog:loggingPrefs", logPrefs);
// 禁用默认应用程序
options.addArguments("--disable-default-apps");
// 静音
options.addArguments("--mute-audio");
// 禁用自动化标志
options.setExperimentalOption("excludeSwitches", new String[]{"enable-automation"});
// 设置代理ip
if (pm != null && Func.isNotBlank(pm.getProxyIp())) {
String proxyAddress = pm.getProxyIp() + ":" + pm.getProxyPort();
Proxy proxy = new Proxy();
proxy.setHttpProxy(proxyAddress);
proxy.setSslProxy(proxyAddress);
options.setProxy(proxy);
}
return new ChromeDriver(options);
}
谷歌浏览器驱动路径:https://googlechromelabs.github.io/chrome-for-testing/#stable
public void handle(Param pm) {
WebDriver driver = null;
try {
if (Func.isBlank(pm.getUserAgent())) {
// 这个工具类只是随机生成userAgent的工具类
pm.setUserAgent(UserAgentUtil.getUserAgent());
}
// 谷歌浏览器驱动路径,注意驱动版本问题
System.setProperty("webdriver.chrome.driver", "F:/chromedriver-win64/chromedriver.exe");
driver = getDriver(pm);
// driver.manage().window().maximize();
// 进入页面
driver.get("https://xxx");
JavascriptExecutor js = (JavascriptExecutor) driver;
//添加cookie
if (pm.getCookies() != null && pm.getCookies().size() > 0) {
setCookie(js, pm.getCookies());
}
// 隐式等待
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
// 其他相关处理代码
...
} catch (Exception e) {
e.printStackTrace();
} finally {
if (driver != null) {
driver.quit();
}
}
}