我有一台服务器向我的Android应用程序发送一个用于的会话cookie 认证通信。我正在尝试使用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);
答案 0 :(得分:51)
谢谢 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();
}
答案 1 :(得分:15)
解决方案: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");
答案 2 :(得分:10)
感谢Android破坏了我的星期天。 。 。下面是修复我的应用程序的内容(在您初始化webview之后)
var customObj ={
data:false,
open:true,
close:true,
error:error
}
我应该说上面的答案可能会有效,但在我的情况下,当Android进入v5 +我的android webview javascript&#39; apps&#39;死亡。
答案 3 :(得分:8)
解决方案是给Android足够的时间来处理cookie。您可以在此处找到更多信息:http://code.walletapp.net/post/46414301269/passing-cookie-to-webview
答案 4 :(得分:3)
我会将该会话cookie保存为首选项,并使用它强制重新填充cookie管理器。听起来会话cookie没有活动重启
答案 5 :(得分:3)
我花了3个半小时的时间来处理一个非常类似的问题。在我的情况下,我有一些电话,我使用DefaulHttpClient
拨打了一个网络服务,然后我想在我的WebView
中设置会话和所有其他相应的Cookie。
我不知道这是否会解决您的问题,因为我不知道您的getCookie()
方法做了什么,但在我的情况下,我实际上不得不打电话。
cookieManager.removeSessionCookie();
首先删除会话cookie,然后重新添加它。我发现当我尝试设置JSESSIONID
cookie而不先删除它时,我想要设置它的值不是保存。不确定这是否会对您有所帮助,但我想我会分享我找到的内容。
答案 6 :(得分:2)
我的工作代码
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"
答案 7 :(得分:1)
我在这里采用了与其他人不同的方法,并且这种方法可以保证在不处理CookieSyncManager的情况下工作(在这里您可以使用语义,例如“请注意偶数sync()异步发生”)。
基本上,我们浏览到正确的域,然后我们从页面上下文执行javascript以设置该域的cookie(与页面本身相同)。该方法的两个缺点是,由于您必须进行额外的http请求,可能会引入额外的往返时间;如果您的网站没有相应的空白页面,它可能会闪现您先加载的网址,然后再将您带到正确的位置。
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风险。
答案 8 :(得分:1)
这是一个有效的代码。
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。
答案 9 :(得分:1)
我在onCreate中用这一行神奇地解决了我所有的cookie问题:
CookieHandler.setDefault(new CookieManager());
编辑:它今天停止了工作。 :(什么废话,安卓。
答案 10 :(得分:1)
也遇到了这个。这就是我的所作所为。
在我的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是另一个包含变量sessionCookie的类,定义为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上使用开发人员控制台并首先测试您的网页,捕获Cookie并检查域名,以便将其存储在某处并确保正确设置正确的域名。
编辑:编辑CookieStoreHelper.cookies到CookieStoreHelper.sessionCookie
答案 11 :(得分:0)
我从经验中发现的注释(至少对于API> = 21的夫妇)感到头痛:
http
和https
的网址不同。为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。我希望我的两分钱能节省一些人的时间,这样您就不必像我一样面对同样的问题。
答案 12 :(得分:0)
我遇到了同样的问题,它将在所有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);
}
}
答案 13 :(得分:0)
经过一段时间的研究,我收集了一些使我着手解决这个问题的作品。一旦弃用CookieSyncManager,这可能是当今在Kotlin中为Webview设置特定Cookie的最佳方法,您不需要其他任何东西。
private fun setCookie(){
val cookieManager = CookieManager.getInstance()
cookieManager.acceptCookie()
val domain = "https://www.yourdomain.com"
webView.webViewClient = WebViewClient()
webViewTest.settings.javaScriptEnabled = true
webViewTest.loadUrl(domain)
cookieManager.setCookie(domain,"$cookieKey=$cookieValue")
cookieManager.setAcceptThirdPartyCookies(view.webViewTest,true)
}
答案 14 :(得分:0)
请注意,最好使用子域而不是通常的URL。因此,请设置.example.com
而不是https://example.com/
。
感谢乔迪·雅各布斯·盖尔(Jody Jacobus Geers)和我这样写的其他人:
if (savedInstanceState == null) {
val cookieManager = CookieManager.getInstance()
cookieManager.acceptCookie()
val domain = ".example.com"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
cookieManager.setCookie(domain, "token=$token") {
view.webView.loadUrl(url)
}
cookieManager.setAcceptThirdPartyCookies(view.webView, true)
} else {
cookieManager.setCookie(domain, "token=$token")
view.webView.loadUrl(url)
}
} else {
// Check whether we're recreating a previously destroyed instance.
view.webView.restoreState(savedInstanceState)
}
答案 15 :(得分:-3)
不要使用您的原始网址
而不是:
cookieManager.setCookie(myUrl, cookieString);
像这样使用它:
cookieManager.setCookie("your url host", cookieString);