周六的時候去參觀瞭36小時編程比賽現場, 氣氛很是激烈, 裡面有一個團隊要做瞭一個移動應用,需要接入公司內域賬號登錄,可是最終頁沒有接入。聯想到我做的就是cas啊,這方面我比較熟悉啊, 隨著使用域賬號登錄公司內賬號的場景增多,為什麼不寫一個demo呢。
說幹就幹, 周六晚上回到住處就開始瞭我的“36小時”編程。
首先,思考一下整體思路,其實cas的整體流程還算比較簡單,我隻需要將在瀏覽器中的整個流程在android上面實現即可,於是一頓狂寫,主要如下:
package com.glodon.cas.model; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; public class GlodonCas { private static DefaultHttpClient httpClient = new DefaultHttpClient(); private static boolean casLogined = false; public final static String CAS_DOMAIN = "https://cas.grandsoft.com.cn"; public String appCallback = null; private boolean isLogined = false; public GlodonCas(String appCallback) { this.appCallback = appCallback; } public boolean login(String username, String password) throws Exception { String service = appCallback; String lt = getLt(); String loginApi = CAS_DOMAIN + "/login"; String params = "username=" + URLEncoder.encode(username) + "&password=" + URLEncoder.encode(password) + "<=" + URLEncoder.encode(lt) + "&service=" + service; byte[] entitydata = params.getBytes(); HttpURLConnection c = (HttpURLConnection) new URL(loginApi) .openConnection(); c.setInstanceFollowRedirects(false); c.setRequestMethod("POST"); c.setDoOutput(true); c.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); c.setRequestProperty("Content-Length", String.valueOf(entitydata.length)); OutputStream outStream = c.getOutputStream(); outStream.write(entitydata); outStream.flush(); outStream.close(); int responeCode = -1; try { responeCode = c.getResponseCode(); } catch (java.io.IOException e) { if (e.getMessage().contains("authentication challenge")) { responeCode = 401; } else { throw e; } } if (responeCode == 303) { get(c.getHeaderField("Location")); isLogined = true; casLogined = true; return true; } else { isLogined = false; casLogined = true; return false; } } public boolean isLogined() { return isLogined; } public static boolean casLogined() { return casLogined; } public static DefaultHttpClient getHttpClient() { return httpClient; } private static String getLt() throws IOException { String httpUrl = CAS_DOMAIN + "/loginTicket"; HttpPost httpPost = new HttpPost(httpUrl); HttpResponse httpRespone = httpClient.execute(httpPost); HttpEntity httpEntity = httpRespone.getEntity(); InputStream inputStream = httpEntity.getContent(); BufferedReader reader = new BufferedReader(new InputStreamReader( inputStream)); String str = ""; String line = null; while ((line = reader.readLine()) != null) { str += line; } return str; } private static String get(String httpUrl) throws Exception { HttpGet httpGet = new HttpGet(httpUrl); InputStream inputStream = null; String bodyStr = ""; HttpResponse httpRespone = httpClient.execute(httpGet); HttpEntity httpEntity = httpRespone.getEntity(); inputStream = httpEntity.getContent(); BufferedReader reader = new BufferedReader(new InputStreamReader( inputStream)); String line = ""; while ((line = reader.readLine()) != null) { bodyStr += line; } return bodyStr; } }
在加上activity的一些控制代碼,最終終於跑通瞭。
現在想想應該還缺一個應用內瀏覽器組件顯示網頁的問題,思路比較簡單:隻需要從httpclient中獲取登錄後的cookie,然後植入瀏覽器組件webview中就行瞭。於是google一下,很快找到相關代碼,復制粘貼,修改, 加個刷新按鈕,ok,搞定。
package com.glodon.cas.activities; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.cookie.Cookie; import android.app.Activity; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.glodon.cas.model.GlodonCas; public class MainActivity extends Activity { private Button btnGetThinkList; private static int LOGIN_REQUEST_CODE = 1; private TextView tvThinkList; private WebView webView; private Button btnRefresh; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnGetThinkList = (Button) findViewById(R.id.btnGetThinkList); tvThinkList = (TextView) findViewById(R.id.tvThinkList); webView = (WebView) findViewById(R.id.webView); btnGetThinkList.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!GlodonCas.casLogined()) { startActivityForResult(new Intent(MainActivity.this, LoginActivity.class), LOGIN_REQUEST_CODE); return; } new ThinkListTask().execute(); } }); webView.getSettings().setJavaScriptEnabled(true); webView.setWebViewClient(new WebViewClient() { public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return false; } }); webView.loadUrl("https://think.grandsoft.com.cn"); btnRefresh = (Button) findViewById(R.id.btnRefresh); btnRefresh.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { List cookies = GlodonCas.getHttpClient() .getCookieStore().getCookies(); if (!cookies.isEmpty()) { Cookie sessionCookie = null; for (int i = 0; i < cookies.size(); i++) { sessionCookie = cookies.get(i); } CookieSyncManager.createInstance(MainActivity.this); CookieManager cookieManager = CookieManager.getInstance(); if (sessionCookie != null) { cookieManager.removeSessionCookie(); String cookieString = sessionCookie.getName() + "=" + sessionCookie.getValue() + "; domain=" + sessionCookie.getDomain(); cookieManager.setCookie("think.grandsoft.com.cn", cookieString); CookieSyncManager.getInstance().sync(); } System.out.println("finish"); webView.loadUrl("https://think.grandsoft.com.cn"); } } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == LOGIN_REQUEST_CODE) { Toast.makeText(this, R.string.login_success, Toast.LENGTH_LONG) .show(); } } class ThinkListTask extends AsyncTask { @Override protected String doInBackground(Void... params) { try { HttpGet httpGet = new HttpGet( "https://think.grandsoft.com.cn/api/weekly_journals"); HttpClient httpClient = GlodonCas.getHttpClient(); HttpResponse httpRespone = httpClient.execute(httpGet); StringBuilder sb = new StringBuilder(); HttpEntity httpEntity = httpRespone.getEntity(); InputStream inputStream = httpEntity.getContent(); BufferedReader reader = new BufferedReader( new InputStreamReader(inputStream)); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } return sb.toString(); } catch (Exception e) { e.printStackTrace(); return null; } } @Override protected void onPostExecute(String thinkList) { tvThinkList.setText(thinkList); } } }
package com.glodon.cas.activities; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import android.app.Activity; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.glodon.cas.model.GlodonCas; public class LoginActivity extends Activity { private static Button btnLogin; private static EditText etUsername; private static EditText etPassword; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); btnLogin = (Button) findViewById(R.id.btnLogin); etUsername = (EditText) findViewById(R.id.etUsername); etPassword = (EditText) findViewById(R.id.etPassword); btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new LoginTask().execute(etUsername.getText().toString(), etPassword.getText().toString()); } }); } public class LoginTask extends AsyncTask { @Override protected Boolean doInBackground(String... args) { try { return new GlodonCas("https://think.grandsoft.com.cn") .login(args[0], args[1]); } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Boolean login_success) { if (login_success == null) { Toast.makeText(LoginActivity.this, R.string.network_error_tip, Toast.LENGTH_LONG).show(); return; } if (login_success) { Intent intent = new Intent(); LoginActivity.this.setResult(RESULT_OK, intent); LoginActivity.this.finish(); } else { Toast.makeText(LoginActivity.this, R.string.login_error_tip, Toast.LENGTH_LONG).show(); } } } }