android - 使用存储在 persistentcookiejar 或其他容器中的 Cookie 来处理 android 中的 okhttp 请求
问题描述
这个问题基本上想知道如何使用存储的cookies进行后续请求。下面的长文只是举例。基本问题是如何对特定网站上的所有请求使用相同的 cookie。
基本上我试图在 android 应用程序中访问网站的登录页面。该网站的工作方式如下。
有 3 个网址需要考虑。
1 -> “ http://www.example.com/timeoutPage ”
2->“ http://www.example.com/mainPage ”
3->“ http://www.example.com/loginPage ”
要考虑的两个要点是
(1)如果我们直接去第三个url(loginPage),它会重定向到第一个url(timeoutPage)。timeoutPage 有一个按钮可以转到 mainPage。
(2) 如果我们转到第二个 url (mainPage),它会给我们一个 cookie。现在,在获取 cookie 后,当我们访问第三个 url (loginPage) 时,我们就可以访问它了。loginPage 有一个验证码,因此必须访问它(loginPage)才能登录。
如果没有在访问 2nd url(mainPage) 时给出的 cookie,我们将无法直接访问 3rd url(loginPage)。
所以我正在做的是制作一个ClearableCookieJar 并将其附加到 OkHttpClient。
OkHttpClient client;
ClearableCookieJar cookieJar;
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(this));
client = new OkHttpClient.Builder()
.cookieJar(cookieJar)
.build();
Request request = new Request.Builder()
.url("http://www.example.com/mainPage")
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
textView.setText("Failed to get response");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
final String myResponse = response.body().string();
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(myResponse);
}
});
}
}
});
一切都很好,因为我可以在我的 textview 中打印 mainPage 的 html。当我对 loginPage 发出另一个请求时,问题就从这里开始了。
request = new Request.Builder()
.url("http://www.example.com/loginPage")
.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0")
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
textView.setText("Failed to get response");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
final String myResponse2 = response.body().string();
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(myResponse2);
}
});
}
}
});
在这里,我再次向 loginPage 发出请求,但我到达了 timeoutPage。我应该如何请求 loginPage url,以便我的请求在向 mainPage 发出请求时发送我存储在 cookieJar 中的 cookie。我想到的一种方法是
request = new Request.Builder()
.url("http://www.example.com/loginPage")
.addHeader("Cookie", cookieStringGivenAtMainPage)
.build();
但我不知道如何访问该 cookieStringGivenAtMainPage。我应该如何到达该 loginPage?
我打印响应的 html,看看我是否到达了正确的页面。
解决方案
看来您想知道的答案是单例模式。请参考下面的示例代码。大约 3 年前,我从 kakao 开发者网站获得了它。
public class NetworkManager {
private static NetworkManager instance;
private OkHttpClient client;
/**
* By using Singleton Pattern we can share cookie, client values.
**/
private NetworkManager() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
Context context = GlobalApplication.getGlobalApplicationContext();
ClearableCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(context));
builder.cookieJar(cookieJar);
builder.followRedirects(true);
builder.addInterceptor(new RedirectInterceptor());
File cacheDir = new File(context.getCacheDir(), "network");
if (!cacheDir.exists()) {
cacheDir.mkdir();
}
Cache cache = new Cache(cacheDir, 10 * 1024 * 1024);
builder.cache(cache);
builder.connectTimeout(30, TimeUnit.SECONDS);
builder.readTimeout(10, TimeUnit.SECONDS);
builder.writeTimeout(10, TimeUnit.SECONDS);
client = builder.build();
}
public static NetworkManager getInstance() {
if (instance == null) {
instance = new NetworkManager();
}
return instance;
}
public OkHttpClient getClient() {
return client;
}
}
此外,下面是示例用法。
OkHttpClient client = NetworkManager.getInstance().getClient();
RequestBody formBody = new FormBody.Builder()
.add("userId", getTargetUserId())
.build();
Request request = new Request.Builder()
.url("www.test.com/insert.php")
.post(formBody)
.build();
client.newCall(request).enqueue(callback);
推荐阅读
- android - 运行应用程序时出错。未找到目标设备
- github-pages - 在 Netlify CMS 的 config.yml 中,如何指定站点位于 repo 的子目录中?
- graphql - 为 writeQuery/readQuery 获取当前 Apollo GraphQL 缓存变量的更好方法?
- node.js - 通过检查数组 Mongodb 中的值从双重嵌套数组中进行投影
- c# - 如何使用 C# stackalloc 并保持相同的代码结构?
- c# - 从数据表错误中获取值对象与目标类型不匹配
- node.js - CDN文件url需要重定向301还是302?
- sql-server - 将一个数据库表中的行插入另一个数据库的两个不同表中
- php - 我得到空数组,在 Codeigniter 中上传多个图像时需要图像数组
- javascript - 在自定义钩子中测试 fetch.catch