android HttpClient+WebView 同步cookie

android客户端经过httpClient或者httpUrlConnection进行登陆后,为了把登陆状态同步到webView中,这时须要进行cookie的同步
javascript


参考:http://segmentfault.com/a/1190000002877843 php


一.cookie同步方式java

下面是登陆线程:android

public class LoginThread extends Thread{
		
	private Handler loginHandler; 
	
	public  LoginThread(Handler loginHandler) {
		this.loginHandler = loginHandler;
	}
	@Override
	public void run() 
	{
		List<String> cookieLst = new ArrayList<String>();
		HttpParams httpParams = new BasicHttpParams();
		ConnManagerParams.setMaxTotalConnections(httpParams, 5);
		ConnManagerParams.setTimeout(httpParams, 15*1000);
		HttpConnectionParams.setSoTimeout(httpParams, 10*1000);
		HttpConnectionParams.setTcpNoDelay(httpParams, true);
		HttpPost httpPost = new HttpPost("http://192.168.1.107/cookie/login.php");
		List<NameValuePair> nvPairs = new ArrayList<NameValuePair>();
		nvPairs.add(new BasicNameValuePair("name", "lisi"));
		nvPairs.add(new BasicNameValuePair("age","22"));
		nvPairs.add(new BasicNameValuePair("gender", "男"));
		
		try {
			UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nvPairs, HTTP.UTF_8);
			httpPost.setEntity(entity);
			HttpClient httpClient =  new DefaultHttpClient();
			
			 //Cookie可能获取不到,所以有必要调用浏览器兼容模式
			HttpClientParams.setCookiePolicy(httpClient.getParams(), CookiePolicy.BROWSER_COMPATIBILITY);  
			   
			HttpResponse httpResponse = httpClient.execute(httpPost);
			if(httpResponse!=null && httpResponse.getStatusLine().getStatusCode()==HttpStatus.SC_OK)
			{
			 	String content = EntityUtils.toString(httpResponse.getEntity());
			 	Log.d("LOGIN", content);
			 	Header[] allHeaders = httpResponse.getAllHeaders();
			 	if(allHeaders!=null)
			 	{
			 		//获取cookie的第一种方式
			 		for (Header header : allHeaders)
			 		{
			 			Log.d("LOGIN", header.getName()+"="+header.getValue());
			 			if("Set-Cookie".equalsIgnoreCase(header.getName()))
			 			{
			 				cookieLst.add(header.getValue());
			 			}
					}
			 	}
			 	//获取cookie的第二种方式
			 	AbstractHttpClient abstractHttpClient = (AbstractHttpClient) httpClient;
			 	CookieStore cookieStore = abstractHttpClient.getCookieStore();
			 	List<Cookie> cookies = cookieStore.getCookies();
			 	for (Cookie cookie : cookies) 
			 	{
			 		Log.d("LOGIN-COOKIE", cookie.getName()+"="+cookie.getValue()+",path="+cookie.getPath()+",domain="+cookie.getDomain()+",expires="+cookie.getExpiryDate());
				}
			 	
			 	if(loginHandler!=null)
 				{
 					Message msg = new Message();
 					msg.obj = cookieLst;
 					msg.what = 200;
 					msg.setTarget(loginHandler);
 					msg.sendToTarget();
 				}
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

下面是WebView主页面Activityweb

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 
public class Main extends Activity implements DownloadListener {
	
	private WebView mWebView;
	
	//extraHeaders经测试不能够同步cookie
	private Map<String, String> extraHeaders;
	
	private final String TAG = "WEB_VIEW";
	
	private final Handler loginHandler = new Handler(){
		
		@Override
		public void handleMessage(Message msg) {
			
			if(msg.what==200)
			{
				List<String> cookies =  (List<String>) msg.obj;
				if(cookies!=null)
				{	
					syncCookieToWebView(cookies);
					mWebView.loadUrl("http://192.168.1.107/cookie/read.php");
				}
			}else{
				super.handleMessage(msg);
			}
		}
		
	};
	
	@SuppressLint("SetJavaScriptEnabled") 
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		mWebView = (WebView) findViewById(R.id.main_webview);
		WebSettings settings = mWebView.getSettings();
		settings.setAppCacheEnabled(true);
		settings.setCacheMode(WebSettings.LOAD_DEFAULT);
		settings.setGeolocationEnabled(true);
		settings.setUseWideViewPort(true);
		settings.setSaveFormData(true);
		settings.setSavePassword(true);
		settings.setSupportZoom(false);
		settings.setLoadsImagesAutomatically(true);
		settings.setBlockNetworkImage(false);
		if(android.os.Build.VERSION.SDK_INT>=11)
		{
			settings.setEnableSmoothTransition(true);
		}
		settings.setJavaScriptCanOpenWindowsAutomatically(false);
		settings.setAllowFileAccess(false);
		settings.setJavaScriptEnabled(true);
		String userAgent = settings.getUserAgentString();
		Log.d(TAG, userAgent);
		if(android.os.Build.VERSION.SDK_INT>=14)
		{
			mWebView.setFitsSystemWindows(true);
		}
		if(mWebView.isHardwareAccelerated())
		{
			mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
		}
		mWebView.setKeepScreenOn(true);
		extraHeaders = new IdentityHashMap<String, String>();
		
		mWebView.setWebViewClient(new WebViewClient(){
			@Override
			public boolean shouldOverrideUrlLoading(WebView view, String url) {
				if(view!=null && !TextUtils.isEmpty(url))
				{
					extraHeaders.put("control-cache", "no-cache,private");
					extraHeaders.put("pragma", "no-cache,no-store");
					extraHeaders.put("expires", "0");
					view.loadUrl(url, extraHeaders);
					return true;
				}
				return super.shouldOverrideUrlLoading(view, url);
			}
		});
		
		mWebView.setDownloadListener(this);
		
		//mWebView.loadUrl("http://shouji.baidu.com/software/?from=web_alad_multi");
		new LoginThread(loginHandler).start();
	}
	//销毁webView
	@Override
	protected void onDestroy() {
		super.onDestroy();
		mWebView.clearFormData();
		mWebView.clearHistory();
		mWebView.destroy();
	}
	
	//监听文件下载,WebView不会自动下载,须要咱们本身构建下载代码
	@Override
	public void onDownloadStart(String url, String userAgent,String contentDisposition, String mimetype, long contentLength) 
	{
		Log.d(TAG, "url="+url);
		Log.d(TAG, "userAgent="+url);
		Log.d(TAG, "contentDisposition="+contentDisposition);
		Log.d(TAG, "mimetype="+mimetype);
		Log.d(TAG, "contentLength="+contentLength);
		
		//第一种下载方式是 自定义的http工具类
		//new DownloadThread(url,contentDisposition,mimetype,contentLength).start();
		
		
		//第二种下载方式是调用系统的webView,具备默认的进度条
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setData(Uri.parse(url));
		startActivity(intent);
		
	}
	/**
	 * cookie同步
	 */
	private void syncCookieToWebView(List<String> cookies)
	{
		CookieSyncManager.createInstance(Main.this);
		CookieManager cm = CookieManager.getInstance();
		cm.setAcceptCookie(true);
		if(cookies!=null)
		{
		    for (String cookie : cookies)
		    {
			cm.setCookie("http://192.168.1.107:80",cookie);//注意端口号和域名,这种方式能够同步全部cookie,包括sessionid
		     }
		}
		CookieSyncManager.getInstance().sync();
	}
}


二.注意:平时开发中Cookie同步是最佳选项,但这并不意味着必定须要使用cookie同步,咱们可使用  token+用户id+登陆时间校验码  进行同步登陆segmentfault


三.对于使用javaInterface进行同步登陆的问题浏览器

javaInterface风险性很高,若是android平台是 4.2+比较安全,但4.2如下版本,安全性不容乐观,好比经过反射形成硬盘被读写的可能性很高!安全

在android 4.2中增长了 @javainterface注解,而且将公开的方法异步化,这样有效的控制了某些不必公开的方法被无心间做为接口公开,致使js发射到硬盘的读写io类,从而发生文件被窃取,垃圾文件堆积,有害文件被下载等问题!cookie


四.目前来讲让全部人使用 4.2+以上版本可能性不大,但尽可能少使用javainterface,转而使用  协议的方式,所谓协议,就是通讯协议,咱们能够分析url参数,从而进行webView和native代码的通讯session

mWebView.setWebViewClient(new WebViewClient(){
			@Override
			public boolean shouldOverrideUrlLoading(WebView view, String url) {
				
			//捕获url的参数值
			
			if(url.indexOf("login")>=0)
			{
			    //客户端代码执行某部分操做----->执行完毕后经过url参数把执行结果返回webView
			    
			}else if(url.indexOf("userCenter")>=0){
			    //客户端代码执行某部分操做----->执行完毕后经过url参数把执行结果返回webView
			}
			return super.shouldOverrideUrlLoading(view, url);
			}
		});

固然,javainterface不推荐,但彻底可使用

view.loadUrl("javascript:dosometing("+"'参数'"+")");


-------------------------------2015-04-30-更新,从webView读取cookie--------------------------------

private class MyWebViewClient extends WebViewClient {

        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            webview.loadUrl(url);
            return true;
        }

        public void onPageFinished(WebView view, String url) {
            CookieManager cookieManager = CookieManager.getInstance();
            String CookieStr = cookieManager.getCookie(url);
            Log.e("sunzn", "Cookies = " + CookieStr);
            super.onPageFinished(view, url);
        }

    }