Задать вопрос
kozinakoff
@kozinakoff
iOS-developer

Как загрузить страницу в WebView с куками?

Есть ссылка на определенную страницу (https://....), которую надо отобразить в WebView. Сайт с авторизацией, авторизационные куки есть (их отдает веб сервис). Но вместо загрузки нужной страницы постоянно получаю отлуп на страницу ввода логина.

Пробовал по всякому, ничего не помогло.

Вариант #1:

CookieManager manager = CookieManager.getInstance();

        manager.setAcceptCookie(true);
        manager.setCookie(url, cookies);

        CookieSyncManager.getInstance().sync();
        webView.loadUrl(url);


где cookies - авторизационные куки.

Вариант #2:

headers.put("Cookie", authCookies);

...

webView.loadUrl(url, headers);


На счет второго варианта иллюзий не питал, в документации ясно сказано: Note that if this map contains any of the headers that are set by default by this WebView, such as those controlling caching, accept types or the User-Agent, their values may be overriden by this WebView's defaults.

Может кто-то из знающих подскажет, в чем проблема или же подскажет, как правильно реализовать загрузку страницы с авторизационными куками?
  • Вопрос задан
  • 9857 просмотров
Подписаться 5 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 3
kozinakoff
@kozinakoff Автор вопроса
iOS-developer
Проблема решается перекрытием в WebViewClient метода shouldInterceptRequest(). WebView подставляет куки не во все запросы (в частности при обращении к ресурсам типа картинок, js, css, ... не подставляет), из-за чего имеем описанную выше проблему.

OkHttpClient client = new OkHttpClient();

    Request req = new Request.Builder()
                            .url(url)
                            .addHeader(HttpHeaders.USER_AGENT, Constants.USER_AGENT_VALUE)
                            .addHeader(HttpHeaders.COOKIE, cookies)
                            .build();

    Response response = client.newCall(req).execute();

    InputStream responseInputStream = response.body().byteStream();

    return new WebResourceResponse(null, null, responseInputStream);


У конструктора WebResourceResponse первые два параметра mimeType и encoding, которые мы можем получить из заголовка response. Но в моем случае, чёрт знает по какой причине, если передавать их в конструктор - получаю 400 Bad Request.
Ответ написан
Комментировать
@fuliozor
Web and Android developer
Я использую следующий код:
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setCookie(url, "sid=" + sid);

webView.loadDataWithBaseURL(null, content, "text/html", "UTF-8", null);
Ответ написан
@antonsheva80
Может не совсем в тему... Бадался с cookie в своем приложении, использовал Retrofit 2 и OkHttp3 (сервер тоже свой - nginx), сколько ни пробовал примеров с getDefaultSharedPreferences() не получалось сохранить ничего кроме PHPSESSID. Решил вручную записывать через SharedPreferences editor.putString(name, value ); научился сохранять и посылать cookie, но сервер не всегда адекватно на них реагировал: заметил, что если PHPSESSID стоит в конце списка посылаемых cookie, то все нормально, иначе сервер высылает код новой сессии. Когда сложил все cookie в одну строку все заработало.

public class AddCookiesInterceptor implements Interceptor {
public static final String PREF_COOKIES = "PREF_COOKIES";
// We're storing our stuff in a database made just for cookies called PREF_COOKIES.
// I reccomend you do this, and don't change this default value.
private Context context;

public AddCookiesInterceptor(Context context) {
this.context = context;
}

@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
Log.i("MyCookie","------------------------------------");
G_.cookie = PrefStorage.getAllProperty();
String val="";
for(Map.Entryentry : G_.cookie.entrySet()){
val += (String)entry.getValue()+"; ";
}
builder.addHeader("Cookie", val);
Log.i("MyCookie",val);
Log.i("MyCookie","------------------------------------");

return chain.proceed(builder.build());
}
}

public class ReceivedCookiesInterceptor implements Interceptor {
private Context context;
public ReceivedCookiesInterceptor(Context context) {
this.context = context;
} // AddCookiesInterceptor()
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
if (!originalResponse.headers("Set-Cookie").isEmpty()) {
String tmp;
for(String header : originalResponse.headers("Set-Cookie")) {
tmp = header.split("=")[0];
PrefStorage.addProperty(tmp, header);
}
}

return originalResponse;
}
}

public class PrefStorage { // обязательно инициализировать
public static final String STORAGE_NAME = "StorageName";

private static SharedPreferences settings = null;
private static SharedPreferences.Editor editor = null;
private static Context context = null;

public static void init( Context cntxt ){
context = cntxt;
}

private static void init(){
settings = context.getSharedPreferences(STORAGE_NAME, Context.MODE_PRIVATE);
editor = settings.edit();
}

public static void addProperty( String name, String value ){
if( settings == null ){
init();
}
editor.putString( name, value );
editor.commit();
}

public static String getProperty( String name ){
if( settings == null ){
init();
}
return settings.getString( name, null );
}
public static Map getAllProperty(){
if( settings == null ){
init();
}
return settings.getAll();
}
}

private NetworkService() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

OkHttpClient.Builder client = new OkHttpClient.Builder()
.addInterceptor(new AddCookiesInterceptor(getApplicationContext()))
.addInterceptor(new ReceivedCookiesInterceptor(getApplicationContext()))
.addInterceptor(interceptor);

mRetrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client.build())
.build();
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы