認証済みの通信に使用するセッションCookieをAndroidアプリに送信するサーバーがあります。同じサーバーを指すURLでWebViewをロードしようとしていますが、認証のためにセッションCookieを渡そうとしています。私はそれが断続的に機能することを観察していますが、その理由はわかりません。同じセッションCookieを使用してサーバー上で他の呼び出しを行いますが、これらは認証に失敗することはありません。 WebViewでURLをロードしようとしたときにのみこの問題が発生し、毎回発生するわけではありません。とてもイライラします。
以下は、これを行うために使用しているコードです。どんな助けも大歓迎です。
String myUrl = ""http://mydomain.com/";
CookieSyncManager.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
Cookie sessionCookie = getCookie();
if(sessionCookie != null){
String cookieString = sessionCookie.getName() +"="+sessionCookie.getValue()+"; domain="+sessionCookie.getDomain();
cookieManager.setCookie(myUrl, cookieString);
CookieSyncManager.getInstance().sync();
}
WebView webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new MyWebViewClient());
webView.loadUrl(myUrl);
おかげでjustingrammens!これでうまくいきました。DefaultHttpClientリクエストとWebViewアクティビティ内でCookieを共有できました。
//------- Native request activity
private DefaultHttpClient httpClient;
public static Cookie cookie = null;
//After Login
List<Cookie> cookies = httpClient.getCookieStore().getCookies();
for (int i = 0; i < cookies.size(); i++) {
cookie = cookies.get(i);
}
//------- Web Browser activity
Cookie sessionCookie = myapp.cookie;
CookieSyncManager.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
if (sessionCookie != null) {
cookieManager.removeSessionCookie();
String cookieString = sessionCookie.getName() + "=" + sessionCookie.getValue() + "; domain=" + sessionCookie.getDomain();
cookieManager.setCookie(myapp.domain, cookieString);
CookieSyncManager.getInstance().sync();
}
ソリューション:Webview CookieSyncManager
CookieSyncManager cookieSyncManager = CookieSyncManager.createInstance(mWebView.getContext());
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.removeSessionCookie();
cookieManager.setCookie("http://xx.example.com","mid="+MySession.GetSession().sessionId+" ; Domain=.example.com");
cookieSyncManager.sync();
String cookie = cookieManager.getCookie("http://xx.example.com");
Log.d(LOGTAG, "cookie ------>"+cookie);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new TuWebViewClient());
mWebView.loadUrl("http://xx.example.com");
日曜日を台無しにしてくれてありがとうAndroid。 。 。私のアプリを修正した理由は次のとおりです(WebViewを初期化した後)
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop ) {
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptThirdPartyCookies( webView, true );
}
上記の回答はおそらく機能するはずですが、私の状況では、Androidがv5 +になった瞬間にAndroid webview javascript 'apps'が停止しました。
解決策は、AndroidにCookieを処理するのに十分な時間を与えることです。詳細については、こちらをご覧ください。 http://code.walletapp.net/post/46414301269/passing-cookie-to-webview
そのセッションCookieを設定として保存し、Cookieマネージャーに強制的に再設定します。セッションCookieがアクティビティの再起動に耐えられないように聞こえます
私は非常によく似た問題に3時間の半分を費やしました。私の場合、DefaulHttpClient
を使用してWebサービスを呼び出した後、WebView
でセッションと他のすべての対応するCookieを設定したかったのです。
あなたのgetCookie()
メソッドが何をするのかわからないので、これがあなたの問題を解決するかどうかはわかりませんが、私の場合は実際に呼び出さなければなりませんでした。
cookieManager.removeSessionCookie();
最初にセッションCookieを削除してから、再度追加します。最初に削除せずにJSESSIONID
Cookieを設定しようとしたときに、設定したい値が保存されていないことがわかりました。これが特定の問題に役立つかどうかはわかりませんが、見つけたものを共有すると思いました。
私の作業コード
public View onCreateView(...){
mWebView = (WebView) view.findViewById(R.id.webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
...
...
...
CookieSyncManager.createInstance(mWebView.getContext());
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
//cookieManager.removeSessionCookie(); // remove
cookieManager.removeAllCookie(); //remove
// Recommended "hack" with a delay between the removal and the installation of "Cookies"
SystemClock.sleep(1000);
cookieManager.setCookie("https://my.app.site.com/", "cookiename=" + value + "; path=/registration" + "; secure"); // ;
CookieSyncManager.getInstance().sync();
mWebView.loadUrl(sp.getString("url", "") + end_url);
return view;
}
クエリをデバッグするには、「cookieManager.setCookie(....);」データベースwebviewCookiesChromium.db(「/data/data/my.app.webview/database」に保存されている)の内容を確認することをお勧めします。そこに正しい設定が表示されます。
「cookieManager.removeSessionCookie();」を無効にするおよび/または「cookieManager.removeAllCookie();」
//cookieManager.removeSessionCookie();
// and/or
//cookieManager.removeAllCookie();"
設定値をブラウザで設定された値と比較します。 「フラグ」ブラウザがインストールされないようになる前に、Cookieのインストール要求を調整してください。クエリは「フラグ」になり得ることがわかりました。
// You may want to add the secure flag for https:
+ "; secure"
// In case you wish to convert session cookies to have an expiration:
+ "; expires=Thu, 01-Jan-2037 00:00:10 GMT"
// These flags I found in the database:
+ "; path=/registration"
+ "; domain=my.app.site.com"
これにも遭遇しました。これが私がしたことです。
AsyncTask内のLoginActivityには、次のものがあります。
CookieStoreHelper.cookieStore = new BasicCookieStore();
BasicHttpContext localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.COOKIE_STORE, CookieStoreHelper.cookieStore);
HttpResponse postResponse = client.execute(httpPost,localContext);
CookieStoreHelper.sessionCookie = CookieStoreHelper.cookieStore.getCookies();
// WHERE CookieStoreHelper.sessionCookieは、リストCookieとして定義された変数sessionCookieを含む別のクラスです。およびcookieStoreは、BasicCookieStore cookieStoreとして定義されます。
次に、私のWebViewが配置されているフラグメントに、次のものがあります。
//DECLARE LIST OF COOKIE
List<Cookie> sessionCookie;
メソッド内、またはWebViewClient()を設定する直前
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
sessionCookie = CookieStoreHelper.cookieStore.getCookies();
CookieSyncManager.createInstance(webView.getContext());
CookieSyncManager.getInstance().startSync();
CookieManager cookieManager = CookieManager.getInstance();
CookieManager.getInstance().setAcceptCookie(true);
if (sessionCookie != null) {
for(Cookie c: sessionCookie){
cookieManager.setCookie(CookieStoreHelper.DOMAIN, c.getName() + "=" + c.getValue());
}
CookieSyncManager.getInstance().sync();
}
webView.setWebViewClient(new WebViewClient() {
//AND SO ON, YOUR CODE
}
クイックヒント:firefoxをfirefoxにインストールするか、chromeで開発者コンソールを使用して、最初にWebページをテストし、Cookieをキャプチャしてドメインを確認してください。 。
編集:CookieStoreHelper.cookiesをCookieStoreHelper.sessionCookieに編集しました
私はここで他の人々とは異なるアプローチをしており、CookieSyncManagerを処理せずに動作することが保証されているアプローチです(「sync()でさえ非同期に発生することに注意してください」などのセマンティクスに左右されます)。
基本的に、正しいドメインを参照し、ページコンテキストからjavascriptを実行して、そのドメインのCookieを設定します(ページ自体と同じ方法)。この方法の2つの欠点は、追加のhttp要求を行う必要があるため、余分な往復時間が発生する可能性があることです。また、サイトに空白ページに相当するものがない場合は、適切な場所に移動する前に最初にロードしたURLがフラッシュされる可能性があります。
import org.Apache.commons.lang.StringEscapeUtils;
import org.Apache.http.cookie.Cookie;
import Android.annotation.SuppressLint;
import Android.webkit.CookieManager;
import Android.webkit.CookieSyncManager;
import Android.webkit.WebView;
import Android.webkit.WebViewClient;
public class WebViewFragment {
private static final String BLANK_PAGE = "/blank.html"
private CookieSyncManager mSyncManager;
private CookieManager mCookieManager;
private String mTargetUrl;
private boolean mInitializedCookies;
private List<Cookie> mAllCookies;
public WebViewFragment(Context ctx) {
// We are still required to create an instance of Cookie/SyncManager.
mSyncManager = CookieSyncManager.createInstance(ctx);
mCookieManager = CookieManager.getInstance();
}
@SuppressLint("SetJavaScriptEnabled") public void loadWebView(
String url, List<Cookie> cookies, String domain) {
final WebView webView = ...
webView.setWebViewClient(new CookeWebViewClient());
webView.getSettings().setJavaScriptEnabled(true);
mInitializedCookies = false;
mTargetUrl = url;
mAllCookies = cookies;
// This is where the hack starts.
// Instead of loading the url, we load a blank page.
webView.loadUrl("http://" + domain + BLANK_PAGE);
}
public static String buildCookieString(final Cookie cookie) {
// You may want to add the secure flag for https:
// + "; secure"
// In case you wish to convert session cookies to have an expiration:
// + "; expires=Thu, 01-Jan-2037 00:00:10 GMT"
// Note that you cannot set the HttpOnly flag as we are using
// javascript to set the cookies.
return cookie.getName() + "=" + cookie.getValue()
+ "; path=" + cookie.getPath()
+ "; domain=" + cookie.getDomain()
};
public synchronized String generateCookieJavascript() {
StringBuilder javascriptCode = new StringBuilder();
javascriptCode.append("javascript:(function(){");
for (final Cookie cookie : mAllCookies) {
String cookieString = buildCookieString(cookie);
javascriptCode.append("document.cookie=\"");
javascriptCode.append(
StringEscapeUtils.escapeJavascriptString(cookieString));
javascriptCode.append("\";");
}
// We use javascript to load the next url because we do not
// receive an onPageFinished event when this code finishes.
javascriptCode.append("document.location=\"");
javascriptCode.append(
StringEscapeUtils.escapeJavascriptString(mTargetUrl));
javascriptCode.append("\";})();");
return javascriptCode.toString();
}
private class CookieWebViewClient extends WebViewClient {
@Override public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (!mInitializedCookies) {
mInitializedCookies = true;
// Run our javascript code now that the temp page is loaded.
view.loadUrl(generateCookieJavascript());
return;
}
}
}
}
Cookieが由来するドメインを信頼する場合、Apacheコモンズなしで逃げることができるかもしれませんが、注意しないとこれがXSSリスクを引き起こす可能性があることを理解する必要があります。
OnCreateの次の1行で、すべてのCookieの問題を魔法のように解決しました。
CookieHandler.setDefault(new CookieManager());
編集:今日は動作しなくなりました。 :(なんてこった、Android。
これは作業用のコードです。
private void setCookie(DefaultHttpClient httpClient, String url) {
List<Cookie> cookies = httpClient.getCookieStore().getCookies();
if (cookies != null) {
CookieSyncManager.createInstance(context);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
for (int i = 0; i < cookies.size(); i++) {
Cookie cookie = cookies.get(i);
String cookieString = cookie.getName() + "=" + cookie.getValue();
cookieManager.setCookie(url, cookieString);
}
CookieSyncManager.getInstance().sync();
}
}
ここで、httpclientは、HttpGet/HttpPostリクエストで使用したDefaultHttpClientオブジェクトです。また、確認する1つのことは、Cookieの名前と値です。
String cookieString = cookie.getName() + "=" + cookie.getValue();
setCookieは、指定されたURLのCookieを設定します。
私の経験からわかった頭痛の種のコメント(少なくとも21以上のAPIの場合):
http
とhttps
のURLは異なります。 http://www.example.com
のCookieの設定は、https://www.example.com
のCookieの設定とは異なりますhttps://www.example.com/
は機能しますが、https://www.example.com
は機能しません。CookieManager.getInstance().setCookie
は非同期操作を実行しています。したがって、設定した直後にURLを読み込んだ場合、Cookieがすでに書き込まれていることは保証されません。予期しない不安定な動作を防ぐには、CookieManager#setCookie(String url、String value、ValueCallback callback)( link )を使用し、コールバックが呼び出された後にURLのロードを開始します。私と同じ問題に直面する必要がないように、私の2セントで何人かの人々の時間を節約できることを願っています。
私は同じ問題に直面しており、すべてのAndroidバージョンでこの問題を解決します
private void setCookie() {
try {
CookieSyncManager.createInstance(context);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
cookieManager.setCookie(Constant.BASE_URL, getCookie(), value -> {
String cookie = cookieManager.getCookie(Constant.BASE_URL);
CookieManager.getInstance().flush();
CustomLog.d("cookie", "cookie ------>" + cookie);
setupWebView();
});
} else {
cookieManager.setCookie(webUrl, getCookie());
new Handler().postDelayed(this::setupWebView, 700);
CookieSyncManager.getInstance().sync();
}
} catch (Exception e) {
CustomLog.e(e);
}
}