From f2ccc62b886d4b2ee6aff983724922ae0b7b1008 Mon Sep 17 00:00:00 2001 From: davigonz Date: Fri, 28 Sep 2018 12:30:06 +0200 Subject: [PATCH] Reimplement cookies handling --- .../android/lib/common/OwnCloudClient.java | 20 ++++++----- .../lib/common/OwnCloudClientManager.java | 5 ++- .../lib/common/SingleSessionManager.java | 6 ++-- .../lib/common/accounts/AccountUtils.java | 5 +-- .../OwnCloudBasicCredentials.java | 3 -- .../android/lib/common/http/HttpClient.java | 36 +++++++++++++++++-- .../RequestHeaderInterceptor.java | 27 ++++++++++++++ .../common/operations/RemoteOperation.java | 1 + 8 files changed, 79 insertions(+), 24 deletions(-) diff --git a/src/com/owncloud/android/lib/common/OwnCloudClient.java b/src/com/owncloud/android/lib/common/OwnCloudClient.java index fa129688..afc035c3 100644 --- a/src/com/owncloud/android/lib/common/OwnCloudClient.java +++ b/src/com/owncloud/android/lib/common/OwnCloudClient.java @@ -29,6 +29,7 @@ import android.accounts.AccountManager; import android.accounts.AccountsException; import android.net.Uri; +import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.authentication.OwnCloudCredentials; import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory; import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials; @@ -91,6 +92,7 @@ public class OwnCloudClient extends HttpClient { Log_OC.d(TAG + " #" + mInstanceNumber, "Creating OwnCloudClient"); clearCredentials(); + clearCookies(); } public void setCredentials(OwnCloudCredentials credentials) { @@ -113,6 +115,10 @@ public class OwnCloudClient extends HttpClient { mCredentials.applyTo(this); } + public void applyCookies() { + AccountUtils.restoreCookies(this.getAccount().getSavedAccount(), this, getContext()); + } + public int executeHttpMethod (HttpBaseMethod method) throws Exception { boolean repeatWithFreshCredentials; @@ -308,15 +314,9 @@ public class OwnCloudClient extends HttpClient { } } - public List getCookiesFromCurrentAccount() { - return getOkHttpClient().cookieJar().loadForRequest(HttpUrl.parse( - getAccount().getBaseUri().toString())); - } - public String getCookiesString() { - String cookiesString = ""; - for (Cookie cookie : getCookiesFromCurrentAccount()) { + for (Cookie cookie : getCookiesFromUrl(HttpUrl.parse(mBaseUri.toString()))) { cookiesString += cookie.toString() + ";"; } @@ -324,8 +324,10 @@ public class OwnCloudClient extends HttpClient { } public void setCookiesForCurrentAccount(List cookies) { - getOkHttpClient().cookieJar().saveFromResponse(HttpUrl.parse( - getAccount().getBaseUri().toString()), cookies); + getOkHttpClient().cookieJar().saveFromResponse( + HttpUrl.parse(getAccount().getBaseUri().toString()), + cookies + ); } public void setOwnCloudVersion(OwnCloudVersion version) { diff --git a/src/com/owncloud/android/lib/common/OwnCloudClientManager.java b/src/com/owncloud/android/lib/common/OwnCloudClientManager.java index 5ef81382..fbaebc06 100644 --- a/src/com/owncloud/android/lib/common/OwnCloudClientManager.java +++ b/src/com/owncloud/android/lib/common/OwnCloudClientManager.java @@ -32,7 +32,6 @@ import android.content.Context; import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException; - /** * Manager to create and reuse OwnCloudClient instances to access remote OC servers. * @@ -43,8 +42,8 @@ import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundExce public interface OwnCloudClientManager { - OwnCloudClient getClientFor(OwnCloudAccount account, Context context) - throws AccountNotFoundException, OperationCanceledException, AuthenticatorException, + OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws AccountNotFoundException, + OperationCanceledException, AuthenticatorException, IOException; OwnCloudClient removeClientFor(OwnCloudAccount account); diff --git a/src/com/owncloud/android/lib/common/SingleSessionManager.java b/src/com/owncloud/android/lib/common/SingleSessionManager.java index f041f465..478490fd 100644 --- a/src/com/owncloud/android/lib/common/SingleSessionManager.java +++ b/src/com/owncloud/android/lib/common/SingleSessionManager.java @@ -65,9 +65,8 @@ public class SingleSessionManager implements OwnCloudClientManager { @Override - public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) - throws AccountNotFoundException, OperationCanceledException, AuthenticatorException, - IOException { + public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws OperationCanceledException, + AuthenticatorException, IOException { if (Log.isLoggable(TAG, Log.DEBUG)) { Log_OC.d(TAG, "getClientFor starting "); @@ -221,7 +220,6 @@ public class SingleSessionManager implements OwnCloudClientManager { reusedClient.getCredentials().getAuthToken())) { reusedClient.setCredentials(recentCredentials); } - } // this method is just a patch; we need to distinguish accounts in the same host but diff --git a/src/com/owncloud/android/lib/common/accounts/AccountUtils.java b/src/com/owncloud/android/lib/common/accounts/AccountUtils.java index fe7d0242..0b0f7ab9 100644 --- a/src/com/owncloud/android/lib/common/accounts/AccountUtils.java +++ b/src/com/owncloud/android/lib/common/accounts/AccountUtils.java @@ -215,7 +215,6 @@ public class AccountUtils { } public static void saveClient(OwnCloudClient client, Account savedAccount, Context context) { - // Account Manager AccountManager ac = AccountManager.get(context.getApplicationContext()); @@ -223,7 +222,7 @@ public class AccountUtils { String cookiesString = client.getCookiesString(); if (!"".equals(cookiesString)) { ac.setUserData(savedAccount, Constants.KEY_COOKIES, cookiesString); - // Log_OC.d(TAG, "Saving Cookies: "+ cookiesString ); + Log_OC.d(TAG, "Saving Cookies: "+ cookiesString ); } } } @@ -252,7 +251,9 @@ public class AccountUtils { String[] rawCookies = cookiesString.split(";"); List cookieList = new ArrayList<>(rawCookies.length); for(String rawCookie : rawCookies) { + rawCookie = rawCookie.replace(" ", ""); final int equalPos = rawCookie.indexOf('='); + if (equalPos == -1) continue; cookieList.add(new Cookie.Builder() .name(rawCookie.substring(0, equalPos)) .value(rawCookie.substring(equalPos + 1)) diff --git a/src/com/owncloud/android/lib/common/authentication/OwnCloudBasicCredentials.java b/src/com/owncloud/android/lib/common/authentication/OwnCloudBasicCredentials.java index 66c0a1db..ecd2a0c4 100644 --- a/src/com/owncloud/android/lib/common/authentication/OwnCloudBasicCredentials.java +++ b/src/com/owncloud/android/lib/common/authentication/OwnCloudBasicCredentials.java @@ -35,18 +35,15 @@ public class OwnCloudBasicCredentials implements OwnCloudCredentials { private String mUsername; private String mPassword; - private boolean mAuthenticationPreemptive; public OwnCloudBasicCredentials(String username, String password) { mUsername = username != null ? username : ""; mPassword = password != null ? password : ""; - mAuthenticationPreemptive = true; } public OwnCloudBasicCredentials(String username, String password, boolean preemptiveMode) { mUsername = username != null ? username : ""; mPassword = password != null ? password : ""; - mAuthenticationPreemptive = preemptiveMode; } @Override diff --git a/src/com/owncloud/android/lib/common/http/HttpClient.java b/src/com/owncloud/android/lib/common/http/HttpClient.java index e03906bb..a29a95af 100644 --- a/src/com/owncloud/android/lib/common/http/HttpClient.java +++ b/src/com/owncloud/android/lib/common/http/HttpClient.java @@ -25,9 +25,7 @@ package com.owncloud.android.lib.common.http; import android.content.Context; -import java.util.concurrent.TimeUnit; -import com.owncloud.android.lib.BuildConfig; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; import com.owncloud.android.lib.common.http.interceptors.HttpInterceptor; import com.owncloud.android.lib.common.http.interceptors.RequestHeaderInterceptor; @@ -35,12 +33,19 @@ import com.owncloud.android.lib.common.network.AdvancedX509TrustManager; import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.utils.Log_OC; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; +import okhttp3.Cookie; +import okhttp3.CookieJar; +import okhttp3.HttpUrl; import okhttp3.OkHttpClient; import okhttp3.Protocol; @@ -54,6 +59,7 @@ public class HttpClient { private static OkHttpClient sOkHttpClient; private static HttpInterceptor sOkHttpInterceptor; private static Context sContext; + private static HashMap> sCookieStore = new HashMap<>(); public static void setContext(Context context) { sContext = context; @@ -70,12 +76,28 @@ public class HttpClient { NetworkUtils.getKnownServersStore(sContext)); final SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[] {trustManager}, null); + + // Automatic cookie handling, NOT PERSISTENT + CookieJar cookieJar = new CookieJar() { + @Override + public void saveFromResponse(HttpUrl url, List cookies) { + sCookieStore.put(url.host(), cookies); + } + + @Override + public List loadForRequest(HttpUrl url) { + List cookies = sCookieStore.get(url.host()); + return cookies != null ? cookies : new ArrayList<>(); + } + }; + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() .addInterceptor(getOkHttpInterceptor()) .protocols(Arrays.asList(Protocol.HTTP_1_1)) .followRedirects(false) .sslSocketFactory(sslContext.getSocketFactory(), trustManager) - .hostnameVerifier((asdf, usdf) -> true); + .hostnameVerifier((asdf, usdf) -> true) + .cookieJar(cookieJar); // TODO: Not verifying the hostname against certificate. ask owncloud security human if this is ok. //.hostnameVerifier(new BrowserCompatHostnameVerifier()); sOkHttpClient = clientBuilder.build(); @@ -128,4 +150,12 @@ public class HttpClient { public static void deleteHeaderForAllRequests(String headerName) { getOkHttpInterceptor().deleteRequestHeaderInterceptor(headerName); } + + public List getCookiesFromUrl(HttpUrl httpUrl) { + return sCookieStore.get(httpUrl.host()); + } + + public void clearCookies() { + sCookieStore.clear(); + } } \ No newline at end of file diff --git a/src/com/owncloud/android/lib/common/http/interceptors/RequestHeaderInterceptor.java b/src/com/owncloud/android/lib/common/http/interceptors/RequestHeaderInterceptor.java index a7b31c26..a998e49b 100644 --- a/src/com/owncloud/android/lib/common/http/interceptors/RequestHeaderInterceptor.java +++ b/src/com/owncloud/android/lib/common/http/interceptors/RequestHeaderInterceptor.java @@ -1,7 +1,34 @@ +/* ownCloud Android Library is available under MIT license + * Copyright (C) 2018 ownCloud GmbH. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + package com.owncloud.android.lib.common.http.interceptors; import okhttp3.Request; +/** + * Intercept requests to update their headers + */ public class RequestHeaderInterceptor implements HttpInterceptor.RequestInterceptor { private String mHeaderName; diff --git a/src/com/owncloud/android/lib/common/operations/RemoteOperation.java b/src/com/owncloud/android/lib/common/operations/RemoteOperation.java index 2dc5487e..0a1b67c7 100644 --- a/src/com/owncloud/android/lib/common/operations/RemoteOperation.java +++ b/src/com/owncloud/android/lib/common/operations/RemoteOperation.java @@ -146,6 +146,7 @@ public abstract class RemoteOperation implements Runnable { mClient = OwnCloudClientManagerFactory.getDefaultSingleton(). getClientFor(ocAccount, mContext); mClient.applyCredentials(); + mClient.applyCookies(); } else { throw new IllegalStateException("Trying to run a remote operation " + "asynchronously with no client and no chance to create one (no account)");