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

在Android volley库中使用Cookie

葛景龙
2023-03-14

有人知道如何使用com将会话cookie附加到请求吗。Android凌空抽射图书馆?当我登录到一个网站时,它会给我一个会话cookie。浏览器会将该cookie与任何后续请求一起发送回。凌空抽射似乎并没有做到这一点,至少不是自动的。

谢谢

共有3个答案

臧俊杰
2023-03-14

Volley的默认HTTP传输代码是HttpUrlConnection。如果我正确阅读了文档,您需要选择自动会话cookie支持:

CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);

另请参阅HttpURLConnection with CookieManager是否应该自动处理会话cookie?

方献
2023-03-14

维米里诺夫是对的!

以下是我解决问题的方法:

请求类:

public class StringRequest extends com.android.volley.toolbox.StringRequest {

    private final Map<String, String> _params;

    /**
     * @param method
     * @param url
     * @param params
     *            A {@link HashMap} to post with the request. Null is allowed
     *            and indicates no parameters will be posted along with request.
     * @param listener
     * @param errorListener
     */
    public StringRequest(int method, String url, Map<String, String> params, Listener<String> listener,
            ErrorListener errorListener) {
        super(method, url, listener, errorListener);

        _params = params;
    }

    @Override
    protected Map<String, String> getParams() {
        return _params;
    }

    /* (non-Javadoc)
     * @see com.android.volley.toolbox.StringRequest#parseNetworkResponse(com.android.volley.NetworkResponse)
     */
    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        // since we don't know which of the two underlying network vehicles
        // will Volley use, we have to handle and store session cookies manually
        MyApp.get().checkSessionCookie(response.headers);

        return super.parseNetworkResponse(response);
    }

    /* (non-Javadoc)
     * @see com.android.volley.Request#getHeaders()
     */
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = super.getHeaders();

        if (headers == null
                || headers.equals(Collections.emptyMap())) {
            headers = new HashMap<String, String>();
        }

        MyApp.get().addSessionCookie(headers);

        return headers;
    }
}

和MyApp:

public class MyApp extends Application {
    private static final String SET_COOKIE_KEY = "Set-Cookie";
    private static final String COOKIE_KEY = "Cookie";
    private static final String SESSION_COOKIE = "sessionid";

    private static MyApp _instance;
  private RequestQueue _requestQueue;
  private SharedPreferences _preferences;

    public static MyApp get() {
        return _instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        _instance = this;
            _preferences = PreferenceManager.getDefaultSharedPreferences(this);
        _requestQueue = Volley.newRequestQueue(this);
    }

    public RequestQueue getRequestQueue() {
        return _requestQueue;
    }


    /**
     * Checks the response headers for session cookie and saves it
     * if it finds it.
     * @param headers Response Headers.
     */
    public final void checkSessionCookie(Map<String, String> headers) {
        if (headers.containsKey(SET_COOKIE_KEY)
                && headers.get(SET_COOKIE_KEY).startsWith(SESSION_COOKIE)) {
                String cookie = headers.get(SET_COOKIE_KEY);
                if (cookie.length() > 0) {
                    String[] splitCookie = cookie.split(";");
                    String[] splitSessionId = splitCookie[0].split("=");
                    cookie = splitSessionId[1];
                    Editor prefEditor = _preferences.edit();
                    prefEditor.putString(SESSION_COOKIE, cookie);
                    prefEditor.commit();
                }
            }
    }

    /**
     * Adds session cookie to headers if exists.
     * @param headers
     */
    public final void addSessionCookie(Map<String, String> headers) {
        String sessionId = _preferences.getString(SESSION_COOKIE, "");
        if (sessionId.length() > 0) {
            StringBuilder builder = new StringBuilder();
            builder.append(SESSION_COOKIE);
            builder.append("=");
            builder.append(sessionId);
            if (headers.containsKey(COOKIE_KEY)) {
                builder.append("; ");
                builder.append(headers.get(COOKIE_KEY));
            }
            headers.put(COOKIE_KEY, builder.toString());
        }
    }

}
席俊驰
2023-03-14

实际上,Volley本身并不会发出HTTP请求,因此也不会直接管理Cookie。相反,它使用HttpStack的一个实例来实现这一点。主要有两种实现方式:

  • HurlStack:在引擎盖下使用HttpUrlConnection
  • HttpClientStack:在引擎盖下使用Apache HttpClient

Cookie管理是这些HttpStacks的责任。他们对饼干的处理方式各不相同。

如果你需要支持

配置HttpClient实例,并将其传递给Volley,以便其在后台使用:

// If you need to directly manipulate cookies later on, hold onto this client
// object as it gives you access to the Cookie Store
DefaultHttpClient httpclient = new DefaultHttpClient();

CookieStore cookieStore = new BasicCookieStore();
httpclient.setCookieStore( cookieStore );

HttpStack httpStack = new HttpClientStack( httpclient );
RequestQueue requestQueue = Volley.newRequestQueue( context, httpStack  );

与手动将cookie插入标头相比,这种方法的优点是可以实现实际的cookie管理。商店中的Cookie将正确响应过期或更新的HTTP控件

我更进一步,对BasicCookieStore进行了子分类,这样我就可以自动将我的Cookie持久化到磁盘。

然而!如果你不需要支持旧版本的Android。只需使用此方法:

// CookieStore is just an interface, you can implement it and do things like
// save the cookies to disk or what ever.
CookieStore cookieStore = new MyCookieStore();
CookieManager manager = new CookieManager( cookieStore, CookiePolicy.ACCEPT_ALL );
CookieHandler.setDefault( manager  );

// Optionally, you can just use the default CookieManager
CookieManager manager = new CookieManager();
CookieHandler.setDefault( manager  );

HttpURLConnection将从中隐式查询CookieManager。HttpUrlConnection的性能也更高,在实现和使用IMO时更简洁。

 类似资料:
  • 问题内容: 我正在尝试使用c创建tar文件。由于某种原因我无法使用 我的代码是: 运行此代码后,当我想解压时 我收到一个错误 我的C代码有什么问题? 问题答案: 我认为您需要在关闭tar文件之前调用tar_append_eof http://linux.die.net/man/3/tar_append_eof。 tar_append_eof()函数将EOF标记(两个全为零的块)写入与t关联的tar

  • 我正在开发一些libs供公司内部使用,它使用spring和spring-Boot。 我的bean定义遇到了问题。我想创建一些不属于我的库的对象bean,例如: 然而,每当我这样做时,它都会影响使用我的库并为它们创建bean的服务,这意味着它们将被迫使用我的Gson或通过定义spring来启用bean重写。主要的允许bean定义覆盖=true,这感觉是错误的。 在库中创建这种bean是一种好的做法吗

  • 我构建了一个ASP。NET核心应用程序,我创建了一个用于单元测试的.NET核心类库。 我想在我的库中使用(获取文件的物理路径),因此我在启动时添加了这一行。我的ASP。NET核心应用程序: 在库中,我添加了对我的ASP.NET应用程序的引用,在我的类中,我写了这个: 但是当我运行它时,它会给我这个错误: 以下构造函数参数没有匹配的设备日期:IHostingEnvironment env 有什么问题

  • 使用本主题了解如何在 Dreamweaver 中创建库项目以及在文档中插入和编辑库项目。 库是一种特殊的 Dreamweaver 文件,其中包含可放置到网页中的一组单个资源或资源副本。库中的这些资源称为库项目。可在库中存储的项目包括图像、表格、声音和使用 Adobe Flash 创建的文件。每当编辑某个库项目时,可以自动更新所有使用该项目的页面。 例如,假设您正在为某公司创建一个大型站点,公司希望

  • 问题内容: 我是Libgdx的新手,在使用游戏数据库时遇到麻烦。 我搜索了有关如何使用Libgdx使SQLite在Android和桌面应用程序上运行的教程,但没有找到一个简单的教程。 我上一次在Android中使用数据库时,创建了一个从扩展的类。 有没有一种简单的方法可以使用Libgdx做到这一点?或者至少,有人可以指出我的逐步教程或类似内容吗? 编辑 我忘了说我正在寻找可以让我管理诸如的版本的东

  • 正如标题所示,我对共享库如何与Rust中的线程局部变量一起工作感到困惑。下面我有一个最小的例子: 在名为的板条箱中: cargo.toml: src/lib.rs: