将Cookie从HttpURLConnection(java.net.CookieManager)传递到WebView(android.webkit.CookieManager)

时间:2012-10-04 16:00:24

标签: android cookies android-webview single-sign-on httpurlconnection

  

我已经看到了关于这应该如何与旧DefaultHttpClient一起使用的答案   但是HttpURLConnection

没有一个很好的例子

我正在使用HttpURLConnection向Web应用程序发出请求。在我的Android应用程序开始时,我使用CookieHandler.setDefault(new CookieManager())自动处理会话cookie,这很正常。

在登录后的某个时刻,我想要使用WebView向用户显示网页应用中的实时网页,而不是使用HttpURLConnection在后​​台下载数据。但是,我想使用我之前建立的相同会话来阻止用户再次登录。

如何将Cookie从java.net.CookieManager使用的HttpURLConnection复制到android.webkit.CookieManager使用的WebView,以便我可以分享会话?

4 个答案:

答案 0 :(得分:51)

我想建议一种完全不同的方法解决您的问题。我们不是将cookie从一个地方复制到另一个地方(手动同步),而是让HttpURLConnection和WebViews使用相同的 cookie存储。

这完全消除了同步的需要。任何一个更新的cookie都会立即自动反映在另一个中。

为此,创建自己的java.net.CookieManager实现,它将所有请求转发到WebViews的webkit android.webkit.CookieManager。

实现:

import java.io.IOException;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.CookieStore;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class WebkitCookieManagerProxy extends CookieManager 
{
    private android.webkit.CookieManager webkitCookieManager;

    public WebkitCookieManagerProxy()
    {
        this(null, null);
    }

    WebkitCookieManagerProxy(CookieStore store, CookiePolicy cookiePolicy)
    {
        super(null, cookiePolicy);

        this.webkitCookieManager = android.webkit.CookieManager.getInstance();
    }

    @Override
    public void put(URI uri, Map<String, List<String>> responseHeaders) throws IOException 
    {
        // make sure our args are valid
        if ((uri == null) || (responseHeaders == null)) return;

        // save our url once
        String url = uri.toString();

        // go over the headers
        for (String headerKey : responseHeaders.keySet()) 
        {
            // ignore headers which aren't cookie related
            if ((headerKey == null) || !(headerKey.equalsIgnoreCase("Set-Cookie2") || headerKey.equalsIgnoreCase("Set-Cookie"))) continue;

            // process each of the headers
            for (String headerValue : responseHeaders.get(headerKey))
            {
                this.webkitCookieManager.setCookie(url, headerValue);
            }
        }
    }

    @Override
    public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) throws IOException 
    {
        // make sure our args are valid
        if ((uri == null) || (requestHeaders == null)) throw new IllegalArgumentException("Argument is null");

        // save our url once
        String url = uri.toString();

        // prepare our response
        Map<String, List<String>> res = new java.util.HashMap<String, List<String>>();

        // get the cookie
        String cookie = this.webkitCookieManager.getCookie(url);

        // return it
        if (cookie != null) res.put("Cookie", Arrays.asList(cookie));
        return res;
    }

    @Override
    public CookieStore getCookieStore() 
    {
        // we don't want anyone to work with this cookie store directly
        throw new UnsupportedOperationException();
    }
}

最后在应用程序初始化时使用它:

android.webkit.CookieSyncManager.createInstance(appContext);
// unrelated, just make sure cookies are generally allowed
android.webkit.CookieManager.getInstance().setAcceptCookie(true);

// magic starts here
WebkitCookieManagerProxy coreCookieManager = new WebkitCookieManagerProxy(null, java.net.CookiePolicy.ACCEPT_ALL);
java.net.CookieHandler.setDefault(coreCookieManager);

答案 1 :(得分:17)

DefaultHttpClient相比,还有一些额外的步骤。关键区别在于如何访问HTTPURLConnection中的现有Cookie:

  1. 致电CookieHandler.getDefault()并将结果转换为java.net.CookieManager
  2. 使用Cookie管理器,请致电getCookieStore()以访问Cookie商店。
  3. 使用Cookie商店,致电get()以访问给定URI的Cookie列表。
  4. 这是一个完整的例子:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Get cookie manager for WebView
        // This must occur before setContentView() instantiates your WebView
        android.webkit.CookieSyncManager webCookieSync =
            CookieSyncManager.createInstance(this);
        android.webkit.CookieManager webCookieManager =
            CookieManager.getInstance();
        webCookieManager.setAcceptCookie(true);
    
        // Get cookie manager for HttpURLConnection
        java.net.CookieStore rawCookieStore = ((java.net.CookieManager)
            CookieHandler.getDefault()).getCookieStore();
    
        // Construct URI
        java.net.URI baseUri = null;
        try {
            baseUri = new URI("http://www.example.com");
        } catch (URISyntaxException e) {
            // Handle invalid URI
            ...
        }
    
        // Copy cookies from HttpURLConnection to WebView
        List<HttpCookie> cookies = rawCookieStore.get(baseUri);
        String url = baseUri.toString();
        for (HttpCookie cookie : cookies) {
            String setCookie = new StringBuilder(cookie.toString())
                .append("; domain=").append(cookie.getDomain())
                .append("; path=").append(cookie.getPath())
                .toString();
            webCookieManager.setCookie(url, setCookie);
        }
    
        // Continue with onCreate
        ...
    }
    

答案 2 :(得分:11)

我在onCreate中用这一行神奇地解决了我所有的cookie问题:

CookieHandler.setDefault(new CookieManager());

答案 3 :(得分:-2)

我遇到了同样的问题,这是我的解决方案:

登录后(因为以前很重要,你可能还没有使用cookie)使用httpurlconnection POST(在getResponseCode之后),我这样做:

 responseCode = connexion.getResponseCode();
 if (responseCode == HttpURLConnection.HTTP_OK) {
     final String COOKIES_HEADER = "Set-Cookie";
     cookie = connexion.getHeaderField(COOKIES_HEADER);
     ...
 }

(其中cookie是我班级的公共字符串)

在webview活动中,我想使用WebView从服务器显示网页,我这样做:

    String url = "http://toto.com/titi.html";        // the url of the page you want to display
    CookieSyncManager.createInstance(getActivity());
    CookieSyncManager.getInstance().startSync();
    android.webkit.CookieManager cookieManager = android.webkit.CookieManager.getInstance();
    cookieManager.setAcceptCookie(true);
    cookieManager.removeSessionCookie();
    cookieManager.setCookie(url, cookie);
    CookieSyncManager.getInstance().sync();

由于我的webview在一个片段中,我不得不使用getActivity()作为Context,我还必须指定android.webkit。在CookieManager之前,否则无法解析(导入java.net而不是android.webkit cookie manager)。

cookie与上面的String相同(在我的片段中,我必须使用:

恢复它
    cookie = getArguments().getString(COOKIE);

在我的MainActivity中,我通过以下方式发送:

    Bundle arg = new Bundle();
    arg.putString(Fragment_Cameras.COOKIE, cookie);
    fragment.setArguments(arg);

我跳这可以帮忙!