biliob/src/main/java/com/yutou/biliapi/net/BiliCookieManager.java
zlzw 44d23b6bac 完善刷新cookie功能
修复ffmpeg下载一大堆的问题
尝试处理了SQLite的内存泄露问题(待确定)
2024-11-25 18:03:17 +08:00

145 lines
6.2 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.yutou.biliapi.net;
import com.alibaba.fastjson2.JSONObject;
import com.yutou.biliapi.api.LoginApi;
import com.yutou.biliapi.bean.login.LoginCookieDatabaseBean;
import com.yutou.biliapi.bean.login.LoginInfoBean;
import com.yutou.biliapi.databases.BiliBiliLoginDatabase;
import com.yutou.common.okhttp.HttpBody;
import com.yutou.common.okhttp.HttpLoggingInterceptor;
import com.yutou.common.utils.ConfigTools;
import com.yutou.common.utils.Log;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.apache.commons.io.IOUtils;
import retrofit2.Response;
import javax.crypto.Cipher;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Iterator;
public class BiliCookieManager {
public static final int COOKIE_INVALID = -101;
public static final int COOKIE_SUCCESS = 0;
private static final String PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLgd2OAkcGVtoE3ThUREbio0Eg\n" +
"Uc/prcajMKXvkCKFCWhJYJcLkcM2DKKcSeFpD/j6Boy538YXnR6VhcuUJOhH2x71\n" +
"nzPjfdTcqMz7djHum0qSZA0AyCBDABUqCrfNgCiJ00Ra7GmRj+YCK1NJEuewlb40\n" +
"JNrRuoEUXpabUzGB8QIDAQAB\n" +
"-----END PUBLIC KEY-----";
/**
* <a href="https://socialsisteryi.github.io/bilibili-API-collect/docs/login/cookie_refresh.html#java">文档地址</a>
*/
public static String getCorrespondPath(String plaintext) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
String publicKeyStr = PUBLIC_KEY
.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "")
.replace("\n", "")
.trim();
byte[] publicBytes = Base64.getDecoder().decode(publicKeyStr);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicBytes);
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
String algorithm = "RSA/ECB/OAEPPadding";
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// Encode the plaintext to bytes
byte[] plaintextBytes = plaintext.getBytes(StandardCharsets.UTF_8);
// Add OAEP padding to the plaintext bytes
OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
cipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParams);
// Encrypt the padded plaintext bytes
byte[] encryptedBytes = cipher.doFinal(plaintextBytes);
// Convert the encrypted bytes to a Base64-encoded string
return new BigInteger(1, encryptedBytes).toString(16);
}
private static String getRefreshCsrf(String htmlContent) {
htmlContent = htmlContent.split("<div id=\"1-name\">")[1].split("</div>")[0];
return htmlContent;
}
public static boolean refreshCookie(LoginCookieDatabaseBean cookie) {
try {
LoginApi api = BiliLoginNetApiManager.getInstance().getLoginApi(cookie.getDedeUserID());
String correspondPath = getCorrespondPath(String.format("refresh_%d", System.currentTimeMillis()));
Log.i("correspondPath = " + correspondPath);
var body = okhttp(correspondPath, cookie);
String refreshCsrf = getRefreshCsrf(body);
Log.i("body = " + refreshCsrf);
String oldCsrf = cookie.getRefreshToken();
Response<HttpBody<LoginInfoBean>> newCookie = api.refreshCookie(cookie.getBiliJct(), refreshCsrf, "main_web", cookie.getRefreshToken()).execute();
LoginCookieDatabaseBean nc = BiliLoginNetApiManager.getInstance().getCookie(newCookie.headers(), newCookie.body());
nc.setGourl(cookie.getGourl());
nc.setSql_time(cookie.getSql_time());
BiliBiliLoginDatabase.getInstance().updateLoginCookie(nc);
api.confirmRefreshCookie(refreshCsrf, oldCsrf).execute();
Log.i("返回正确");
return true;
} catch (Exception e) {
Log.e(e);
return false;
}
}
public static String okhttp(String correspondPath, LoginCookieDatabaseBean cookie) {
JSONObject json = JSONObject.parseObject(JSONObject.toJSONString(cookie));
StringBuilder ck = new StringBuilder();
json.remove("sql_time");
json.remove("gourl");
json.remove("Expires");
json.remove("path");
json.remove("refresh_token");
json.put("SESSDATA", URLDecoder.decode(json.getString("SESSDATA"), StandardCharsets.UTF_8));
// 构建Cookie字符串去掉最后一个分号
Iterator<String> keys = json.keySet().iterator();
while (keys.hasNext()) {
String key = keys.next();
ck.append(key).append("=").append(json.getString(key));
if (keys.hasNext()) {
ck.append(";");
}
}
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://www.bilibili.com/correspond/1/" + correspondPath)
.method("GET", null) // GET请求不带body
.addHeader("Cookie", ck.toString())
.addHeader("User-Agent", ConfigTools.getUserAgent())
.addHeader("Accept", "*/*")
.addHeader("Host", "www.bilibili.com")
.addHeader("Connection", "keep-alive")
.build();
try {
okhttp3.Response execute = client.newCall(request).execute();
while (execute.code() == 404) {
execute = client.newCall(request).execute();
}
return IOUtils.toString(execute.body().byteStream(), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException("Failed to execute HTTP request", e);
}
}
}