Programing

Android WebView 쿠키 문제

lottogame 2020. 10. 6. 07:44
반응형

Android WebView 쿠키 문제


인증 된 통신에 사용할 세션 쿠키를 내 Android 앱에 보내는 서버가 있습니다. 동일한 서버를 가리키는 URL로 WebView를로드하려고하는데 인증을 위해 세션 쿠키를 전달하려고합니다. 간헐적으로 작동하는 것을 관찰하고 있지만 이유를 모르겠습니다. 동일한 세션 쿠키를 사용하여 내 서버에서 다른 호출을 만들고 인증에 실패하지 않습니다. 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 활동 내에서 쿠키를 공유했습니다.

//------- 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");

내 일요일을 망치는 안드로이드에 감사드립니다. . . 내 앱을 수정 한 이유는 다음과 같습니다 (웹뷰를 초기화 한 후).

if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ) {

  CookieManager cookieManager = CookieManager.getInstance();

  cookieManager.setAcceptThirdPartyCookies( webView, true );

}

위의 답변이 아마도 작동 할 것이라고 말해야하지만 제 상황에서는 Android가 v5 +로 전환되는 순간 내 Android webview javascript 'apps'가 죽었습니다.


해결책은 Android가 쿠키를 처리 할 수있는 충분한 시간을 제공하는 것입니다. 자세한 정보는 여기에서 찾을 수 있습니다 : http://code.walletapp.net/post/46414301269/passing-cookie-to-webview


세션 쿠키를 기본 설정으로 저장하고 쿠키 관리자를 강제로 다시 채 웁니다. 활동이 다시 시작되지 않는 세션 쿠키가 들립니다.


저는 매우 유사한 문제를 해결하기 위해 3 시간 중 절반 이상을 보냈습니다. 제 경우에는 a를 사용하여 웹 서비스에 여러 번 호출 DefaulHttpClient한 다음 .NET에서 세션 및 기타 모든 해당 쿠키를 설정하고 싶었습니다 WebView.

나는 당신의 getCookie()방법이 무엇을하는지 모르기 때문에 이것이 당신의 문제를 해결할 수 있을지 모르겠지만 , 제 경우에는 실제로 전화해야했습니다.

cookieManager.removeSessionCookie();

먼저 세션 쿠키를 제거한 다음 다시 추가하십시오. JSESSIONID쿠키를 먼저 제거하지 않고 설정하려고 할 때 설정 하려는 값이 저장되지 않는 것을 발견했습니다. 이것이 특정 문제에 도움이 될지 확실하지 않지만 내가 찾은 것을 공유 할 것이라고 생각했습니다.


내 작업 코드

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();"

설정 값을 브라우저에서 설정 한 값과 비교하십시오. "플래그"브라우저가 설치되지 않을 때까지 귀하가 결정한 내용에 맞을 때까지 쿠키 설치 요청을 조정하십시오. 쿼리가 "플래그"일 수 있음을 발견했습니다.

// 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"

여기 다른 사람들과는 다른 접근 방식이 있으며 CookieSyncManager ( "sync ()조차 비동기 적으로 발생 함"과 같은 의미 체계의 자비에있는 경우)를 처리하지 않고도 작동이 보장되는 접근 방식입니다.

기본적으로 올바른 도메인을 찾은 다음 페이지 컨텍스트에서 자바 스크립트를 실행하여 해당 도메인에 대한 쿠키를 설정합니다 (페이지 자체와 동일한 방식). 이 방법의 두 가지 단점은 추가 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;
            }
        }
    }
}

쿠키가있는 도메인을 신뢰하면 아파치 커먼즈 없이도 벗어날 수 있지만 조심하지 않으면 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 개체입니다. 또한 확인해야 할 한 가지는 쿠키 이름과 값입니다.

String cookieString = cookie.getName() + "=" + cookie.getValue();

setCookie will the set the cookie for the given URL.


I magically solved all my cookie problems with this one line in onCreate:

CookieHandler.setDefault(new CookieManager());

edit: it stopped working today. :( what the crap, android.


Encountered this too also. Here's what I did.

On my LoginActivity, inside my AsyncTask, I have the following:

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 is another class containing the variable sessionCookie defined as List cookies; and cookieStore define as BasicCookieStore cookieStore;

Then on my Fragment, where my WebView is located i have the following:

//DECLARE LIST OF COOKIE
List<Cookie> sessionCookie;

inside my method or just before you are setting the 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
 }

Quick Tip: Have firebug installed on firefox or use developer console on chrome and test first your webpage, capture the Cookie and check the domain so you can store it somewhere and be sure that you are correctly setting the right domain.

Edit: edited CookieStoreHelper.cookies to CookieStoreHelper.sessionCookie


Couple of comments (at least for APIs >= 21) which I found out from my experience and gave me headaches:

  1. http and https urls are different. Setting a cookie for http://www.example.com is different than setting a cookie for https://www.example.com
  2. A slash in the end of the url can also make a difference. In my case https://www.example.com/ works but https://www.example.com does not work.
  3. CookieManager.getInstance().setCookie is performing an asynchronous operation. So, if you load a url right away after you set it, it is not guaranteed that the cookies will have already been written. To prevent unexpected and unstable behaviours, use the CookieManager#setCookie(String url, String value, ValueCallback callback) (link) and start loading the url after the callback will be called.

I hope my two cents save some time from some people so you won't have to face the same problems like I did.


I have faced same problem and It will resolve this issue in all android versions

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);
    }
}

Don't use your raw url

Instead of:

cookieManager.setCookie(myUrl, cookieString); 

use it like this:

cookieManager.setCookie("your url host", cookieString); 

참고URL : https://stackoverflow.com/questions/1652850/android-webview-cookie-problem

반응형