1
0
mirror of https://github.com/owncloud/android-library.git synced 2025-06-08 00:16:09 +00:00

Reimplement cookies handling

This commit is contained in:
davigonz 2018-09-28 12:30:06 +02:00
parent ae7be42ec3
commit f2ccc62b88
8 changed files with 79 additions and 24 deletions

View File

@ -29,6 +29,7 @@ import android.accounts.AccountManager;
import android.accounts.AccountsException; import android.accounts.AccountsException;
import android.net.Uri; 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.OwnCloudCredentials;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory; import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials; 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"); Log_OC.d(TAG + " #" + mInstanceNumber, "Creating OwnCloudClient");
clearCredentials(); clearCredentials();
clearCookies();
} }
public void setCredentials(OwnCloudCredentials credentials) { public void setCredentials(OwnCloudCredentials credentials) {
@ -113,6 +115,10 @@ public class OwnCloudClient extends HttpClient {
mCredentials.applyTo(this); mCredentials.applyTo(this);
} }
public void applyCookies() {
AccountUtils.restoreCookies(this.getAccount().getSavedAccount(), this, getContext());
}
public int executeHttpMethod (HttpBaseMethod method) throws Exception { public int executeHttpMethod (HttpBaseMethod method) throws Exception {
boolean repeatWithFreshCredentials; boolean repeatWithFreshCredentials;
@ -308,15 +314,9 @@ public class OwnCloudClient extends HttpClient {
} }
} }
public List<Cookie> getCookiesFromCurrentAccount() {
return getOkHttpClient().cookieJar().loadForRequest(HttpUrl.parse(
getAccount().getBaseUri().toString()));
}
public String getCookiesString() { public String getCookiesString() {
String cookiesString = ""; String cookiesString = "";
for (Cookie cookie : getCookiesFromCurrentAccount()) { for (Cookie cookie : getCookiesFromUrl(HttpUrl.parse(mBaseUri.toString()))) {
cookiesString += cookie.toString() + ";"; cookiesString += cookie.toString() + ";";
} }
@ -324,8 +324,10 @@ public class OwnCloudClient extends HttpClient {
} }
public void setCookiesForCurrentAccount(List<Cookie> cookies) { public void setCookiesForCurrentAccount(List<Cookie> cookies) {
getOkHttpClient().cookieJar().saveFromResponse(HttpUrl.parse( getOkHttpClient().cookieJar().saveFromResponse(
getAccount().getBaseUri().toString()), cookies); HttpUrl.parse(getAccount().getBaseUri().toString()),
cookies
);
} }
public void setOwnCloudVersion(OwnCloudVersion version) { public void setOwnCloudVersion(OwnCloudVersion version) {

View File

@ -32,7 +32,6 @@ import android.content.Context;
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException; import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
/** /**
* Manager to create and reuse OwnCloudClient instances to access remote OC servers. * 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 { public interface OwnCloudClientManager {
OwnCloudClient getClientFor(OwnCloudAccount account, Context context) OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws AccountNotFoundException,
throws AccountNotFoundException, OperationCanceledException, AuthenticatorException, OperationCanceledException, AuthenticatorException,
IOException; IOException;
OwnCloudClient removeClientFor(OwnCloudAccount account); OwnCloudClient removeClientFor(OwnCloudAccount account);

View File

@ -65,9 +65,8 @@ public class SingleSessionManager implements OwnCloudClientManager {
@Override @Override
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws OperationCanceledException,
throws AccountNotFoundException, OperationCanceledException, AuthenticatorException, AuthenticatorException, IOException {
IOException {
if (Log.isLoggable(TAG, Log.DEBUG)) { if (Log.isLoggable(TAG, Log.DEBUG)) {
Log_OC.d(TAG, "getClientFor starting "); Log_OC.d(TAG, "getClientFor starting ");
@ -221,7 +220,6 @@ public class SingleSessionManager implements OwnCloudClientManager {
reusedClient.getCredentials().getAuthToken())) { reusedClient.getCredentials().getAuthToken())) {
reusedClient.setCredentials(recentCredentials); reusedClient.setCredentials(recentCredentials);
} }
} }
// this method is just a patch; we need to distinguish accounts in the same host but // this method is just a patch; we need to distinguish accounts in the same host but

View File

@ -215,7 +215,6 @@ public class AccountUtils {
} }
public static void saveClient(OwnCloudClient client, Account savedAccount, Context context) { public static void saveClient(OwnCloudClient client, Account savedAccount, Context context) {
// Account Manager // Account Manager
AccountManager ac = AccountManager.get(context.getApplicationContext()); AccountManager ac = AccountManager.get(context.getApplicationContext());
@ -223,7 +222,7 @@ public class AccountUtils {
String cookiesString = client.getCookiesString(); String cookiesString = client.getCookiesString();
if (!"".equals(cookiesString)) { if (!"".equals(cookiesString)) {
ac.setUserData(savedAccount, Constants.KEY_COOKIES, 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(";"); String[] rawCookies = cookiesString.split(";");
List<Cookie> cookieList = new ArrayList<>(rawCookies.length); List<Cookie> cookieList = new ArrayList<>(rawCookies.length);
for(String rawCookie : rawCookies) { for(String rawCookie : rawCookies) {
rawCookie = rawCookie.replace(" ", "");
final int equalPos = rawCookie.indexOf('='); final int equalPos = rawCookie.indexOf('=');
if (equalPos == -1) continue;
cookieList.add(new Cookie.Builder() cookieList.add(new Cookie.Builder()
.name(rawCookie.substring(0, equalPos)) .name(rawCookie.substring(0, equalPos))
.value(rawCookie.substring(equalPos + 1)) .value(rawCookie.substring(equalPos + 1))

View File

@ -35,18 +35,15 @@ public class OwnCloudBasicCredentials implements OwnCloudCredentials {
private String mUsername; private String mUsername;
private String mPassword; private String mPassword;
private boolean mAuthenticationPreemptive;
public OwnCloudBasicCredentials(String username, String password) { public OwnCloudBasicCredentials(String username, String password) {
mUsername = username != null ? username : ""; mUsername = username != null ? username : "";
mPassword = password != null ? password : ""; mPassword = password != null ? password : "";
mAuthenticationPreemptive = true;
} }
public OwnCloudBasicCredentials(String username, String password, boolean preemptiveMode) { public OwnCloudBasicCredentials(String username, String password, boolean preemptiveMode) {
mUsername = username != null ? username : ""; mUsername = username != null ? username : "";
mPassword = password != null ? password : ""; mPassword = password != null ? password : "";
mAuthenticationPreemptive = preemptiveMode;
} }
@Override @Override

View File

@ -25,9 +25,7 @@
package com.owncloud.android.lib.common.http; package com.owncloud.android.lib.common.http;
import android.content.Context; 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.OwnCloudClientManagerFactory;
import com.owncloud.android.lib.common.http.interceptors.HttpInterceptor; import com.owncloud.android.lib.common.http.interceptors.HttpInterceptor;
import com.owncloud.android.lib.common.http.interceptors.RequestHeaderInterceptor; 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.network.NetworkUtils;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import java.util.ArrayList;
import java.util.Arrays; 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.SSLContext;
import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager; import javax.net.ssl.X509TrustManager;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.Protocol; import okhttp3.Protocol;
@ -54,6 +59,7 @@ public class HttpClient {
private static OkHttpClient sOkHttpClient; private static OkHttpClient sOkHttpClient;
private static HttpInterceptor sOkHttpInterceptor; private static HttpInterceptor sOkHttpInterceptor;
private static Context sContext; private static Context sContext;
private static HashMap<String, List<Cookie>> sCookieStore = new HashMap<>();
public static void setContext(Context context) { public static void setContext(Context context) {
sContext = context; sContext = context;
@ -70,12 +76,28 @@ public class HttpClient {
NetworkUtils.getKnownServersStore(sContext)); NetworkUtils.getKnownServersStore(sContext));
final SSLContext sslContext = SSLContext.getInstance("TLS"); final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] {trustManager}, null); sslContext.init(null, new TrustManager[] {trustManager}, null);
// Automatic cookie handling, NOT PERSISTENT
CookieJar cookieJar = new CookieJar() {
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
sCookieStore.put(url.host(), cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> cookies = sCookieStore.get(url.host());
return cookies != null ? cookies : new ArrayList<>();
}
};
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
.addInterceptor(getOkHttpInterceptor()) .addInterceptor(getOkHttpInterceptor())
.protocols(Arrays.asList(Protocol.HTTP_1_1)) .protocols(Arrays.asList(Protocol.HTTP_1_1))
.followRedirects(false) .followRedirects(false)
.sslSocketFactory(sslContext.getSocketFactory(), trustManager) .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. // TODO: Not verifying the hostname against certificate. ask owncloud security human if this is ok.
//.hostnameVerifier(new BrowserCompatHostnameVerifier()); //.hostnameVerifier(new BrowserCompatHostnameVerifier());
sOkHttpClient = clientBuilder.build(); sOkHttpClient = clientBuilder.build();
@ -128,4 +150,12 @@ public class HttpClient {
public static void deleteHeaderForAllRequests(String headerName) { public static void deleteHeaderForAllRequests(String headerName) {
getOkHttpInterceptor().deleteRequestHeaderInterceptor(headerName); getOkHttpInterceptor().deleteRequestHeaderInterceptor(headerName);
} }
public List<Cookie> getCookiesFromUrl(HttpUrl httpUrl) {
return sCookieStore.get(httpUrl.host());
}
public void clearCookies() {
sCookieStore.clear();
}
} }

View File

@ -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; package com.owncloud.android.lib.common.http.interceptors;
import okhttp3.Request; import okhttp3.Request;
/**
* Intercept requests to update their headers
*/
public class RequestHeaderInterceptor implements HttpInterceptor.RequestInterceptor { public class RequestHeaderInterceptor implements HttpInterceptor.RequestInterceptor {
private String mHeaderName; private String mHeaderName;

View File

@ -146,6 +146,7 @@ public abstract class RemoteOperation<T extends Object> implements Runnable {
mClient = OwnCloudClientManagerFactory.getDefaultSingleton(). mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
getClientFor(ocAccount, mContext); getClientFor(ocAccount, mContext);
mClient.applyCredentials(); mClient.applyCredentials();
mClient.applyCookies();
} else { } else {
throw new IllegalStateException("Trying to run a remote operation " + throw new IllegalStateException("Trying to run a remote operation " +
"asynchronously with no client and no chance to create one (no account)"); "asynchronously with no client and no chance to create one (no account)");