Android开发WordPress的客户端, 登录时Cookie(httpOnly)的问题

曾经用Android开发过学校教务系统的登录功能(jsp/tomcat),能够成功模拟出Http请求. 但是WordPress的登录功能实现起来要绕一个弯子. 不能直接用HttpClient来得到cookie.

这位兄弟遇到的问题跟我是一样的 http://hi.baidu.com/xtitman/item/eeaef4c7d4a0e2bc0c0a7b69最后也是成功用socket方法把功能实现了. 其中为如何用socket模拟http的post/get请求消息头以及消息体纠结了几个小时。

My codes are as follows. Please ignore the animation part and focus on the method run() in class MyThread. It's just a demo and I didn't make any post-procession with the result. And if you have any question about this demo, please send an e-mail to [email protected] which I would appreciate much.

 

 

package login.activities;

import home.activities.R;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URLEncoder;
import java.net.UnknownHostException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import system.standards.Standards;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

public class LoginActivity extends Standards
{
	private Button leftBall = null;
	private Button rightBall = null;
	private Button submit = null;

	private EditText username = null;
	private String usernameText = null;
	private EditText password = null;
	private String passwordText = null;

	private DisplayMetrics metrics = null;

	private static final String serverIpAddress = "***.***.***.***";
	private static final String encodedUsername = "wordpress_af8ad83c4c8ce7c7f7efddce117a5a74=admin%";
	private static final String encodedPassword = "wordpress_logged_in_af8ad83c4c8ce7c7f7efddce117a5a74=admin%";
	// private static final String LOGIN_URL =
	// "http://atom.student.utwente.nl/wp-login.php";
	private static String encodedUsernameText = "";
	private static String encodedPasswordText = "";

	private boolean isAnimated = false;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);

		setContentView(R.layout.login);

		getAllWidgets();

		submit.setOnClickListener(new Button.OnClickListener()
		{

			public void onClick(View arg0)
			{
				// TODO Auto-generated method stub
				usernameText = username.getText().toString();
				passwordText = password.getText().toString();
				Log.d("DEBUG", "USERNAME: " + usernameText);
				Log.d("DEBUG", "PASSWORD: " + passwordText);

				doLogin(usernameText, passwordText);
			}

		});
	}

	private void doLogin(String usernameText, String passwordText)
	{
		MyLoginThread myLoginThread = new MyLoginThread(usernameText,
				passwordText);

		myLoginThread.start();
	}

	private class MyLoginThread extends Thread
	{
		private String logUsername = null;
		private String logPassword = null;

		public MyLoginThread(String logUsername, String logPassword)
		{
			this.logUsername = logUsername;
			this.logPassword = logPassword;
		}

		@Override
		public void run()
		{
			// TODO Auto-generated method stub
			// 首先采用socket方式模拟浏览器发出第一个Post请求访问第一个网页(携带的参数是username和 password, 消息头以及消息体必须遵守post/get的严格格式)
			// 之后得到第一个网页的HttpResponse, 从中提取出由服务器加密之后的username和password
			// 第一个网页由于返回状态码302因而需要进行重定向到真正的DashBoard即登录成功页面
			// 重定向是需要重新发送一个请求, 通过FireBug可以得知需要得到的是GET请求
			// 并且携带的cookie是包含上次请求返回的加密之后username和password
			// 所以这次模拟的重定向可以直接使用HttpGet, 然后调用httpGet.addHeader("Cookie", 加密之后的用户名 + 加密之后的密码 + 其他信息(是静态的信息, 可以由FireBug探测得知));
			// 從而得到真正的DashBoard页面
			// 为什么第一次请求需要用底层的socket呢?而不直接使用HttpPost/HttpClient呢?可以通过使用相应方法(getHeaders()?getCookie()?)得到cookies, 而不需要自己来拼串
			// 原因是发现第一次的请求返回的cookies, 是 httpOnly的, 采用HttpClient方式遍历headers可以发现是打印不出来的!也就是说不能用上层的这些方法了
			// 所以之后采用socket方法模拟POST请求了, 得到的是未经过加工处理的response, 采用String的相应方法拼串可以提取出cookies
			
			try
			{
				Socket socket = new Socket(serverIpAddress, 80);

				BufferedReader br = new BufferedReader(new InputStreamReader(
						socket.getInputStream(), "UTF-8"));
				OutputStream os = socket.getOutputStream();

				StringBuffer sb = new StringBuffer(
						"POST /wp-login.php HTTP/1.1\r\n");
				sb.append("Host: atom.student.utwente.nl\r\n");
				sb.append("Connection: keep-alive\r\n");
				sb.append("Content-Length: 114\r\n");
				sb.append("Cache-Control: max-age=0\r\n");
				sb.append("Origin: http://atom.student.utwente.nl\r\n");
				sb.append("User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1\r\n");
				sb.append("Content-Type: application/x-www-form-urlencoded\r\n");
				sb.append("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n");
				sb.append("Referer: http://atom.student.utwente.nl/wp-login.php\r\n");
				sb.append("Accept-Encoding: gzip,deflate,sdch");
				sb.append("Accept-Language: en,en-US;q=0.8,zh;q=0.6,zh-CN;q=0.4,nl;q=0.2\r\n");
				sb.append("Accept-Charset: UTF-8,*;q=0.5\r\n");
				sb.append("Cookie: wordpress_polylang=en; wp-settings-1=imgsize%3Dfull%26editor%3Dhtml%26hidetb%3D1%26libraryContent%3Dbrowse; wp-settings-time-1=1357880535; wordpress_test_cookie=WP+Cookie+check\r\n");

				sb.append("\r\n");

				sb.append(URLEncoder.encode("log", "UTF-8"));
				sb.append("=");
				sb.append(URLEncoder.encode(logUsername, "UTF-8"));
				sb.append("&");
				sb.append(URLEncoder.encode("pwd", "UTF-8"));
				sb.append("=");
				sb.append(URLEncoder.encode(logPassword, "UTF-8"));
				sb.append("&");
				sb.append(URLEncoder.encode("wp-submit", "UTF-8"));
				sb.append("=");
				sb.append(URLEncoder.encode("Log In", "UTF-8"));
				sb.append("&");
				sb.append(URLEncoder.encode("redirect_to", "UTF-8"));
				sb.append("=");
				sb.append(URLEncoder.encode(
						"http://atom.student.utwente.nl/wp-admin/", "UTF-8"));
				sb.append("&");
				sb.append(URLEncoder.encode("testcookie", "UTF-8"));
				sb.append("=");
				sb.append(URLEncoder.encode("1", "UTF-8"));

				os.write(sb.toString().getBytes());

				String tmp = "";
				StringBuffer resultBuffer = new StringBuffer();

				while ((tmp = br.readLine()) != null)
				{
					System.out.println(tmp);
					resultBuffer.append(tmp);
				}

				int usernameStartPosition = resultBuffer
						.indexOf(encodedUsername) + encodedUsername.length();
				int passwordStartPosition = resultBuffer
						.indexOf(encodedPassword) + encodedPassword.length();

				encodedUsernameText = resultBuffer.substring(
						usernameStartPosition, usernameStartPosition + 47);
				encodedPasswordText = resultBuffer.substring(
						passwordStartPosition, passwordStartPosition + 47);

				System.out.println("encodedUsernameText: "
						+ encodedUsernameText);
				System.out.println("encodedPasswordText: "
						+ encodedPasswordText);
				os.close();
				br.close();

				DefaultHttpClient httpClient = new DefaultHttpClient();
				HttpGet httpGet = new HttpGet(
						"http://atom.student.utwente.nl/wp-admin/");

				httpGet.addHeader(
						"Cookie",
						encodedUsername
								+ encodedUsernameText
								+ "; wordpress_polylang=en; wp-settings-1=imgsize%3Dfull%26editor%3Dhtml%26hidetb%3D1%26libraryContent%3Dbrowse; wp-settings-time-1=1357880535; wordpress_test_cookie=WP+Cookie+check; "
								+ encodedPassword + encodedPasswordText);

				HttpResponse httpResponse = null;
				httpResponse = httpClient.execute(httpGet);

				HttpEntity httpEntity = null;

				String resultText = null;

				if (httpResponse.getStatusLine().getStatusCode() == 200)
				{
					System.out.println("LOGIN SUCCEED!");
					
					Toast.makeText(LoginActivity.this,
							"LOGIN SUCCEED!", Toast.LENGTH_SHORT)
							.show();
					
					httpEntity = httpResponse.getEntity();

					resultText = EntityUtils.toString(httpEntity, "UTF-8");

					System.out.println(resultText);
				} else
				{
					Toast.makeText(LoginActivity.this,
							"Invalid Username or Password!", Toast.LENGTH_SHORT)
							.show();
				}
			} catch (UnknownHostException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			super.run();
		}
	}

	private class MyAnimationMoveListener implements AnimationListener
	{

		@Override
		public void onAnimationEnd(Animation animation)
		{
			// TODO Auto-generated method stub
			// clear all animations
			leftBall.clearAnimation();
			rightBall.clearAnimation();
			findViewById(R.id.loginlay3).clearAnimation();
			findViewById(R.id.loginlay4).clearAnimation();
			findViewById(R.id.loginlay5).clearAnimation();

			// widgets translations & invisiable
			RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
					leftBall.getWidth(), leftBall.getHeight());
			// params.leftMargin = (screenWidth / 2 - leftBall.getWidth() -
			// screenWidth / 3);
			params.addRule(RelativeLayout.LEFT_OF, R.id.loginlay3);
			leftBall.setLayoutParams(params);

			RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(
					rightBall.getWidth(), rightBall.getHeight());

			params2.addRule(RelativeLayout.RIGHT_OF, R.id.loginlay3);
			rightBall.setLayoutParams(params2);

			System.out.println("rightSpace: " + rightBall.getRight());

			// rightBall.setLayoutParams(params2);

			findViewById(R.id.loginlay3).setVisibility(View.VISIBLE);
			findViewById(R.id.loginlay4).setVisibility(View.VISIBLE);
			findViewById(R.id.loginlay5).setVisibility(View.VISIBLE);

		}

		@Override
		public void onAnimationRepeat(Animation animation)
		{
			// TODO Auto-generated method stub

		}

		@Override
		public void onAnimationStart(Animation animation)
		{
			// TODO Auto-generated method stub

		}

	}

	private class MyAnimationReturnListener implements AnimationListener
	{

		@Override
		public void onAnimationEnd(Animation animation)
		{
			// TODO Auto-generated method stub
			// clear all animations
			leftBall.clearAnimation();
			rightBall.clearAnimation();
			findViewById(R.id.loginlay3).clearAnimation();
			findViewById(R.id.loginlay4).clearAnimation();
			findViewById(R.id.loginlay5).clearAnimation();

			// widgets translations & invisiable
			RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
					leftBall.getWidth(), leftBall.getHeight());
			params.addRule(RelativeLayout.LEFT_OF, R.id.nothing);
			leftBall.setLayoutParams(params);

			RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(
					rightBall.getWidth(), rightBall.getHeight());
			params2.addRule(RelativeLayout.RIGHT_OF, R.id.left_ball);
			rightBall.setLayoutParams(params2);

			findViewById(R.id.loginlay3).setVisibility(View.INVISIBLE);
			findViewById(R.id.loginlay4).setVisibility(View.INVISIBLE);
			findViewById(R.id.loginlay5).setVisibility(View.INVISIBLE);
		}

		@Override
		public void onAnimationRepeat(Animation animation)
		{
			// TODO Auto-generated method stub

		}

		@Override
		public void onAnimationStart(Animation animation)
		{
			// TODO Auto-generated method stub

		}

	}

	private void startAllWidgetAnimation(boolean hasAnimated)
	{
		int leftBallTranslation = 0;
		int rightBallTranslation = 0;

		MyAnimationReturnListener returnListener = new MyAnimationReturnListener();
		MyAnimationMoveListener moveListener = new MyAnimationMoveListener();

		AlphaAnimation anim3 = null;
		Animation anim2 = null;
		Animation anim1 = null;

		if (false == hasAnimated)
		{
			leftBallTranslation = -findViewById(R.id.loginlay3).getWidth() / 2;

			System.out.println("R.id.loginlay3 width: "
					+ findViewById(R.id.loginlay3).getWidth());

			rightBallTranslation = -leftBallTranslation;
			anim3 = new AlphaAnimation(0.0f, 1.0f);

			anim3.setAnimationListener(moveListener);

		} else
		{
			leftBallTranslation = findViewById(R.id.loginlay3).getWidth() / 2;
			rightBallTranslation = -leftBallTranslation;
			anim3 = new AlphaAnimation(1.0f, 0.0f);

			anim3.setAnimationListener(returnListener);
		}

		anim1 = new TranslateAnimation(0, leftBallTranslation, 0, 0);
		anim1.setDuration(2000);
		anim1.setFillAfter(true);

		anim2 = new TranslateAnimation(0, rightBallTranslation, 0, 0);
		anim2.setDuration(2000);
		anim2.setFillAfter(true);

		// if (false == hasAnimated)
		// {
		// anim1.setAnimationListener(moveListener);
		// anim2.setAnimationListener(moveListener);
		// } else
		// {
		// anim1.setAnimationListener(returnListener);
		// anim2.setAnimationListener(returnListener);
		// }

		leftBall.startAnimation(anim1);
		rightBall.startAnimation(anim2);

		// edit text animation

		anim3.setStartOffset(1000);
		anim3.setDuration(1000);
		anim3.setFillAfter(true);
		// usernameTag & usernameText layer animation
		((LinearLayout) findViewById(R.id.loginlay3)).startAnimation(anim3);
		// passwordTag & passwordText layer animation
		((LinearLayout) findViewById(R.id.loginlay4)).startAnimation(anim3);
		// submit button animation
		((LinearLayout) findViewById(R.id.loginlay5)).startAnimation(anim3);
	}

	public void myClickHandler(final View view)
	{
		int id = view.getId();

		if ((id == R.id.left_ball || id == R.id.right_ball)
				&& false == isAnimated)
		{
			// leftBall moves left, rightBall moves right, loginField turns
			// visible
			startAllWidgetAnimation(false);
			isAnimated = true;

		} else if (true == isAnimated)
		{
			// leftBall moves right, rightBall moves left, loginField turns
			// invisible, return to initial state
			startAllWidgetAnimation(true);
			isAnimated = false;
		}
	}

	private void getAllWidgets()
	{
		metrics = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(metrics);

		// screenWidth = metrics.widthPixels;

		leftBall = (Button) findViewById(R.id.left_ball);
		rightBall = (Button) findViewById(R.id.right_ball);
		submit = (Button) findViewById(R.id.login_submit);

		username = (EditText) findViewById(R.id.username);
		password = (EditText) findViewById(R.id.password);
	}

}

你可能感兴趣的:(android,wordpress,登录,cookie,HttpOnly)