当前位置: 首页 > 知识库问答 >
问题:

使用存储的Cookie在持续Cookiejar或其他一些容器的okhttp请求在Android

薛烨霖
2023-03-14

这个问题主要是想知道如何在后续请求中使用存储的cookie。下面的长文本只是一个例子。基本问题是如何对特定网站上的所有请求使用相同的cookie。

基本上,我正在尝试进入android应用程序中的网站登录页面。该网站的工作方式如下。

有3个网址需要考虑。

1-

2 -

3 -

需要考虑的两个要点是

(1) 如果我们直接转到第三个url(登录页面),它会重定向到第一个url(timeoutPage)。timeoutPage有一个按钮可以转到主页。

(2) 如果我们转到第二个url(主页),它会给我们一个cookie。现在,在获得cookie后,当我们访问第三个url(loginPage)时,我们就可以访问它了。登录页面有一个验证码,所以必须访问它(登录页面)才能登录。

如果没有cookie(在访问第二个url(主页)时提供),我们无法直接访问第三个url(登录页面)。

所以我正在做的是做一个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);
                        }
                    });
                }
            }
        });

在这里之前一切都很好,因为我可以在我的文本视图中打印主页的html。当我再次请求登录页面时,问题从这里开始。

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);
                        }
                    });
                }
            }
        });

在这里,我再次请求登录页面,但我到达了timeoutPage。我应该如何请求登录页面url,以便我的请求在向主页发出请求时发送存储在cookieJar中的cookie。我想到的一个方法

request = new Request.Builder()
                .url("http://www.example.com/loginPage")
                .addHeader("Cookie", cookieStringGivenAtMainPage)
                .build();

但我不知道如何访问CookiesTringGiveNatMain页面。我该如何到达登录页面?

我打印响应的html,看看我是否到达了正确的页面。

共有1个答案

郎成弘
2023-03-14

你想知道的答案似乎是单身模式。请参考下面的示例代码。大约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应用程序中,我试图从android-async-超文本传输协议切换到支持异步网络sind版本2.0的okhttp。虽然前者附带了持久cookie存储的实现,但我不知道如何为实现类似的东西。 在我的应用程序中,我有一个登录例程,在此期间会发送一个请求,如果成功,应该设置一个cookie。此cookie应附加到所有后续网络请求中,并应在应用程序重新启动后继续有效。 我在SO上找到了

  • 问题内容: 我们生产中的一个线程在整个生命周期中都在遇到每个错误并正在为其服务的每个请求上产生错误!现在已经有好 几天 了!这怎么可能?我们如何防止这种情况继续下去? 背景 我们在uWSGI(4个进程,2个线程)上使用了Flask应用程序,并且Flask-SQLAlchemy为我们提供了到SQL Server的数据库连接。 当我们的生产中的一个线程在Flask-SQLAlchemy方法内部拆除请求

  • 问题内容: 我正在尝试评估诸如Jackrabbit和ModeShape之类的内容存储库(JSR283),但我必须承认,我不理解首先解决什么问题,即使它是该项目的不错选择。您认为哪种情况是最好的解决方案?除了大小之外,它与关系数据库不一样吗?为什么?指出真实世界示例的加分。 提前致谢。 问题答案: JCR存储库不同于RDBMS,因为JCR存储库: 是分层的,使您可以按照与您的需求紧密匹配的结构来组织

  • 问题内容: 我正在使用Axios从客户端向我的Express.js服务器发送请求。 我在客户端上设置了一个cookie,我想从所有Axios请求中读取该cookie,而无需手动将其手动添加到请求中。 这是我的客户端请求示例: 我试图通过在Express.js服务器中使用以下属性来访问标头或cookie: 他们两个都不包含任何cookie。我正在使用cookie解析器中间件: 如何使Axios自动在

  • 代码: 试图从第一个Get请求中获取一个变量,并将该变量注入第二个请求中,但尽管使用了文档,还是无法实现。可能有些事我不明白。 当我使用断点并在流程中导航时,会话执行似乎发生在其他两个请求都已完成之后(此时已经太晚了)。似乎无法在两个请求之间执行会话。

  • 在Oracle中,需要在存储过程中多次重用查询结果。想知道临时表是推荐的方式还是其他方式... 首先,我基于某些输入参数创建一个结果集。 然后做一些检查,看看是否有任何结果集行出现在表1中。简单的连接和计数就足够了。如果算 为了获得最佳性能,应该使用临时表还是其他表? 谢谢