Maintain session between HttpUrlConnection Calls (Native/Webview)

后端 未结 4 1785
长情又很酷
长情又很酷 2021-02-12 21:01

Let me start with what I desire:

I want to make an app which is part native and part webviews.

Problem - Maintai

相关标签:
4条回答
  • 2021-02-12 21:46

    Try to add this two lines anywhere you want. (Maybe if you extend Application class and add them on the onCreate() method would be better)

    CookieManager cookieManager = new CookieManager();
    CookieHandler.setDefault(cookieManager);
    
    0 讨论(0)
  • 2021-02-12 21:55

    The closest I could get to this is, by using a webview as login. Then you can continue your session in the HttpUrlConnection, with the cookies fetched from webview. The cookies can be used as follows:

    HttpURLConnection urlConnection = null;
    try {
        urlConnection = (HttpURLConnection) url.openConnection();
    
        // Fetch and set cookies in requests
        CookieManager cookieManager = CookieManager.getInstance();
        String cookie = cookieManager.getCookie(urlConnection.getURL().toString());
        if (cookie != null) {
            urlConnection.setRequestProperty("Cookie", cookie);
        }
        urlConnection.connect();
    
        // Get cookies from responses and save into the cookie manager
        List cookieList = urlConnection.getHeaderFields().get("Set-Cookie");
        if (cookieList != null) {
            for (String cookieTemp : cookieList) {
                cookieManager.setCookie(urlConnection.getURL().toString(), cookieTemp);
            }
        }
    
        InputStream in = new BufferedInputStream (urlConnection.getInputStream());
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (urlConnection != null) {
            urlConnection.disconnect();
        }
    }
    
    0 讨论(0)
  • 2021-02-12 21:55

    It is Cookie header you are suppose to send on the request, not Set-Cookie.
    Please read https://tools.ietf.org/html/rfc6265 for examples.

    When your client receives session cookie in HTTP response header as

    Set-Cookie: PHPSESSID=e407ef64abb71b1ea2b8e4b30db76cf0; path=/
    

    It should add this cookie to subsequent HTTP requests header as

    Cookie: PHPSESSID=e407ef64abb71b1ea2b8e4b30db76cf0
    

    EDIT:

    The native PHPSESSID is a bit confusing, but it should be ok to use the last value of ci_session cookie, e.g. from the response

    Set-Cookie ,Value : [PHPSESSID=e407ef64abb71b1ea2b8e4b30db76cf0; path=/, ci_session=a%3A0%3A%7B%7D; expires=Thu, 06-Nov-2014 16:54:57 GMT; Max-Age=-31500000; path=/, ci_session=a%3A5%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%22caedca696344458e7aa1b4ad02b3cfa0%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A13%3A%22182.59.130.42%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A60%3A%22Dalvik%2F2.1.0+%28Linux%3B+U%3B+Android+5.1.1%3B+Nexus+5+Build%2FLMY48B%29%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1446792897%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3B%7D5f4013e4a2edd2eb891ec8a2b8e8716e; expires=Sun, 05-Nov-2017 06:54:57 GMT; Max-Age=63072000; path=/, ci_session=a%3A4%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%22caedca696344458e7aa1b4ad02b3cfa0%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A13%3A%22182.59.130.42%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A60%3A%22Dalvik%2F2.1.0+%28Linux%3B+U%3B+Android+5.1.1%3B+Nexus+5+Build%2FLMY48B%29%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1446792897%3B%7Dc7eaa0945a7056db3cb9d336a02e5ecb; expires=Sun, 05-Nov-2017 06:54:57 GMT; Max-Age=63072000; path=/, ci_session=a%3A4%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%22caedca696344458e7aa1b4ad02b3cfa0%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A13%3A%22182.59.130.42%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A60%3A%22Dalvik%2F2.1.0+%28Linux%3B+U%3B+Android+5.1.1%3B+Nexus+5+Build%2FLMY48B%29%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1446792897%3B%7Dc7eaa0945a7056db3cb9d336a02e5ecb; expires=Sun, 05-Nov-2017 06:54:57 GMT; Max-Age=63072000; path=/]
    

    add to the folowing header to the webview request:

    abc.put("Cookie", "ci_session=a%3A4%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%2221d4f88af57e9c7477f48e0695bdb979%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A13%3A%22182.59.216.32%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A40%3A%22Apache-HttpClient%2FUNAVAILABLE+%28java+1.4%29%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1446884548%3B%7D30e2cc6561b3fb9659c7809d0c82946d");
    

    I would recommend to iterate over SSID = map.get("Set-Cookie"), test each individual 'Set-Cookie' header with something like /(ci_session=.*?);/ regex, and return the last match.

    Please note, that User-Agent header from your webview should match user_agent in the session. In the cookie above it is Apache-HttpClient/UNAVAILABLE (java 1.4), and it seems that webview uses Dalvik/2.1.0 (Linux; U; Android 5.1.1; Nexus 5 Build/LMY48B).

    0 讨论(0)
  • 2021-02-12 22:06

    A brilliant implementation of the java.net.CookieManager.

    I've implemented my own idea. It's actually pretty cool. I've created my own implementation of java.net.CookieManager which forwards all requests to the WebViews' webkit android.webkit.CookieManager. This means no sync is required and HttpURLConnection uses the same cookie storage as the WebViews.



    Class WebkitCookieManagerProxy:

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

    And use it by doing this on your application initialization:

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

    Ref: Talkol - WebkitCookieManagerProxy

    0 讨论(0)
提交回复
热议问题