Android WebView Cookie问题
我有一个服务器,发送我的android应用程序会话cookie用于authentication通信。 我想加载一个指向同一个服务器的URL的WebView,我想通过会话cookie进行身份validation。 我正在观察,它间歇性地工作,但我不知道为什么。 我使用相同的会话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(); }
解决scheme: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");
解决scheme是给Android足够的时间来处理cookie。 你可以在这里find更多的信息: http : //code.walletapp.net/post/46414301269/passing-cookie-to-webview
我花了三个半小时的时间来处理一个非常类似的问题。 在我的情况下,我有一些调用,我使用DefaulHttpClient
对Web服务,然后我想在我的WebView
设置会话和所有其他相应的Cookie。
我不知道这是否能解决你的问题,因为我不知道你的getCookie()
方法是干什么的,但在我的情况下,我实际上不得不打电话。
cookieManager.removeSessionCookie();
首先删除会话cookie,然后重新添加它。 我发现当我试图设置JSESSIONID
cookie没有先删除它,我想要设置它的值不被保存。 不知道这是否会帮助你特定的问题,但我想我会分享我发现的。
感谢Android毁了我的星期天。 。 。 下面是什么修复了我的Apps(在你初始化你的webview之后)
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ) { CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptThirdPartyCookies( webView, true ); }
我应该说上面的答案可能会工作,但在我的情况下,Android去了V5 +我的android webview javascript'应用程序'死了。
我会将该会话cookie保存为首选项,并强制重新填充cookiepipe理器。 这听起来是不幸的活动重新启动会话cookie
我在这里有一个不同于其他人的方法,它是一种保证工作而不处理CookieSyncManager的方法(在这种情况下,你受到像“请注意即使sync()同步发生”)语义的束缚。
本质上,我们浏览到正确的域名,然后我们从页面上下文执行JavaScript来为该域设置cookie(与页面本身相同)。 该方法的两个缺点是可能由于额外的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 commons就可以离开,但是你必须明白,如果你不小心,这可能会带来XSS风险。
这是一段代码。
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对象。 还有一点要确定的是cookie的名称和价值,应该给予
String cookieString = cookie.getName() + "=" + cookie.getValue();
setCookie将为给定的URL设置cookie。
我使用onCreate中的这一行神奇地解决了我所有的cookie问题:
CookieHandler.setDefault(new CookieManager());
编辑:它今天停止工作。 :(什么废话,机器人。
也遇到了这个。 这是我做的。
在我的LoginActivity,在我的AsyncTask,我有以下几点:
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是另一个包含variablessessionCookie的类,定义为List cookies; 和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上安装firebug,或者在chrome上使用开发者控制台,首先testing你的网页,捕获Cookie并检查域名,以便将它存储在某个地方,并确保你正确设置了正确的域名。
编辑:编辑CookieStoreHelper.cookies到CookieStoreHelper.sessionCookie
我的工作代码
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; }
要debugging查询,“cookieManager.setCookie(….);” 我build议您查看数据库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"
不要使用您的原始url
cookieManager.setCookie(myUrl, cookieString); you need like this:cookieManager.setCookie("your url host", cookieString);