This commit is contained in:
2024-11-08 18:12:02 +08:00
parent 6d00813311
commit 6e2cea8186
32 changed files with 396 additions and 201 deletions

View File

@@ -3,9 +3,11 @@ package com.yutou.biliapi.api;
import com.yutou.biliapi.bean.login.CheckCookieBean;
import com.yutou.biliapi.bean.login.LoginInfoBean;
import com.yutou.biliapi.bean.login.QRCodeGenerateBean;
import com.yutou.common.okhttp.FileBody;
import com.yutou.common.okhttp.HttpBody;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface LoginApi {
@@ -27,5 +29,13 @@ public interface LoginApi {
@GET("x/passport-login/web/cookie/info")
Call<HttpBody<CheckCookieBean>> checkCookie();
@GET("https://www.bilibili.com/correspond/1/{correspondPath}")
Call<FileBody<String>> getCorrespond(@Path("correspondPath") String correspondPath);
@GET("/x/passport-login/web/cookie/refresh")
Call<HttpBody<LoginInfoBean>> refreshCookie(@Query("csrf") String csrf
, @Query("refresh_csrf") String refresh_csrf
, @Query("source") String source
, @Query("refresh_token") String ac_time_value
);
}

View File

@@ -27,6 +27,8 @@ public class LoginCookieDatabaseBean extends AbsDatabasesBean {
String sid;
@JSONField(name = "gourl")
String gourl;
@JSONField(name ="refresh_token")
String refreshToken;
public LoginCookieDatabaseBean() {
super("login_cookie", System.currentTimeMillis());

View File

@@ -54,6 +54,9 @@ public class BiliBiliLoginDatabase extends SQLiteManager {
return null;
}
public List<LoginCookieDatabaseBean> getAllCookies(){
return super.get(cookie.getTableName(), LoginCookieDatabaseBean.class);
}
public LoginUserDatabaseBean getUser(String userId) {
List<LoginUserDatabaseBean> list = getAllUser();

View File

@@ -1,15 +1,22 @@
package com.yutou.biliapi.net;
import com.yutou.biliapi.bean.login.CheckCookieBean;
import com.yutou.common.inter.IHttpApiCheckCallback;
import com.yutou.common.okhttp.HttpCallback;
import com.yutou.biliapi.api.LoginApi;
import com.yutou.biliapi.bean.login.LoginCookieDatabaseBean;
import com.yutou.common.okhttp.FileBody;
import com.yutou.common.utils.Log;
import com.yutou.common.utils.RSAUtils;
import okhttp3.Headers;
import com.yutou.common.utils.WebClient;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import retrofit2.Response;
import javax.crypto.Cipher;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
@@ -19,8 +26,9 @@ import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class BiliCookieManager {
public static final int COOKIE_INVALID = -101;
public static final int COOKIE_SUCCESS = 0;
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" +
@@ -29,62 +37,54 @@ public class BiliCookieManager {
"JNrRuoEUXpabUzGB8QIDAQAB\n" +
"-----END PUBLIC KEY-----";
public void checkCookie(IHttpApiCheckCallback<Integer> callback){
BiliLoginNetApiManager.getInstance().getLoginApi(null)
.checkCookie().enqueue(new HttpCallback<CheckCookieBean>() {
@Override
public void onResponse(Headers headers, int code, String status, CheckCookieBean response, String rawResponse) {
if(code==-101){
// TODO cookie失效需要重新登录
callback.onError(COOKIE_INVALID,"cookie失效需要重新登录");
return;
}
if(response.isRefresh()){
refreshCookie();
}
callback.onSuccess(COOKIE_SUCCESS);
}
@Override
public void onFailure(Throwable throwable) {
}
});
}
/**
* <a href="https://socialsisteryi.github.io/bilibili-API-collect/docs/login/cookie_refresh.html#java">文档地址</a>
*/
private void refreshCookie(){
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 void resetCookie(LoginCookieDatabaseBean cookie) {
try {
String refreshTime = String.format("refresh_%d", System.currentTimeMillis());
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);
LoginApi api = BiliLoginNetApiManager.getInstance().getLoginApi(cookie.getDedeUserID());
String correspondPath = getCorrespondPath(String.format("refresh_%d", System.currentTimeMillis()));
System.out.println("correspondPath = " + correspondPath);
Response<FileBody<String>> body = api.getCorrespond(correspondPath).execute();
String string = IOUtils.toString(body.body().getInputStream(), StandardCharsets.UTF_8);
String refreshCsrf = getRefreshCsrf(string);
System.out.println("body = " + refreshCsrf);
String algorithm = "RSA/ECB/OAEPPadding";
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// Encode the plaintext to bytes
byte[] plaintextBytes = refreshTime.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
String encrypted = new BigInteger(1, encryptedBytes).toString(16);
}catch (Exception e){
Log.e(e);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -106,6 +106,7 @@ public class BiliLoginNetApiManager extends BaseApi {
if (!list.isEmpty()) {
ck.put("gourl", bd);
LoginCookieDatabaseBean cookie = JSONObject.parseObject(ck.toString(), LoginCookieDatabaseBean.class);
cookie.setRefreshToken(httpBody.getData().getRefresh_token());
cancel();
callback.onResponse(headers, LOGIN_SUCCESS, "ok", cookie, ck.toString());