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-----"; /** * 文档地址 */ 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("
")[1].split("
")[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> 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 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); } } }